在NodeJS上阻塞function

我正在使用NodeJS构build一个API的SDK,可以在这里find。 我的问题是,当用户声明模块时,它会提供我需要validation的用户名和密码以及必须用于将来调用的令牌。 所以,这个令牌存储在irecarga.token,并且为了每一个将来的呼叫,我将不得不使用它来识别用户。 我的问题是,如果用户在声明后直接调用另一个函数,声明可能不会及时完成(因为它执行HTTP POST),属性标记将为空。

// module declaration which requires a HTTP call and updates irecarga.token var irecarga = require('../')({ username: process.env.IRECARGA_USERNAME, password: process.env.IRECARGA_PASSWORD }) // function called straight after declaration which uses irecarga.token irecarga.getServiceProviders(48, function(err, data){ // this code won't even run because the token = null will break the code console.log('err: ', err) console.log('data', data) }) 

所以,我看到了很多用Node创build阻塞函数的解决scheme,我可以使用callback函数或其他模块来发送我想执行的函数作为其他函数的参数。

这些解决scheme很可能会工作,但代码将是丑陋和混乱。 此外,我不认为自己在创新,实际上这就是我看到像微软和谷歌这样的大公司宣布他们的API密钥。

我在这里错过了什么? 有什么我可以添加validationfunction,使任何方法的iRecarga等待,直到validation完成?

使用await您可以添加一个单线,以等待解决承诺,等待initializatoin(身份validation)完成的每个API方法。 这是你可以做的一个方法。 我用babel使用最新的语法。

 // myapi.js import login from './auth'; import {query, insert} from './db'; let authenticated = null, user = null; async function getProviders({regionId}) { await authenticated; return await query({region:regionId}); } async function order({provider, service}) { await authenticated; return await insert({entity:'orders'}, {service, user}); } export default function ({username, password}) { authenticated = new Promise( async (resolve, reject) => { const valid = await login({username, password}); if (valid) { user = username; resolve(); } else { reject(); } }); return {getProviders, order}; } // test/myapi.js import myapi from '../myapi'; async function test() { let api = myapi({username:'tom', password:'1234'}); let providers = await api.getProviders({regionId:48}); console.log(providers); let providers2 = await api.getProviders({regionId:5}); console.log(providers2); } test().catch(console.error); 

在node.js中,你不会使asynchronous事物阻塞。 相反,你使用它们作为asynchronous,并在它们上面创build一个asynchronous接口。

所以,你需要为你的初始化提供一个asynchronous接口,以便调用者知道什么时候完成了初始化,何时调用其他方法是安全的或者可能的。 有很多不同的方法来做到这一点:

  1. require()()返回一个promise,parsing的值就是你的模块对象。 然后,调用者执行一个.then()并在该callback中可以使用您正确初始化的模块。

  2. 将一个callback传递给模块初始化,并要求所有模块使用该callback(与上面的承诺相同,只是使用常规callback)。

  3. 不要将凭据传递给构造函数。 相反,请创build一个asynchronous.login()方法,该方法返回一个承诺,并指示调用方在parsing的login承诺内不要使用该接口。

例如,它可能看起来像这样:

 require('../')({ username: process.env.IRECARGA_USERNAME, password: process.env.IRECARGA_PASSWORD }).then(function(irecarga) { // function called straight after declaration which uses irecarga.token // this method should probably be changed to use promises irecarga.getServiceProviders(48, function(err, data){ console.log('err: ', err) console.log('data', data) }); }).catch(function(err) { // handle intiialization error here });