由于js语言的特性,使用node开发程序的时候常常会遇到异步处理的问题。对于以前专长App开发的我来讲,会纠结node中实现客户端API请求的“最佳实践”。下面以OAuth2.0为场景,须要处理的流程:javascript
一开始,咱们使用了闭包嵌套闭包的方式实现,形如:html
request(options, (res, error)=>{ //handle res and error request(options2, (res2, error2)=>{ //handle res2 and error2 }) })
咱们能够容许函数的异步执行,但大多数人在思考问题的时候,尤为在解决如上的场景时,仍是但愿能采用线性地处理方式。因而,咱们使用request-promise-native
,配合aync/await,相似:java
1 (async ()=> { 2 let access = await requestpromise(authoptions).then((value)=>{ 3 return value; 4 }).catch((error)=>{ 5 return error; 6 }); 7 console.log('access', access); 8 })();
使用async/await的时候,须要知道:node
能够猜测 request-promise-native
一定是对request进行了Promise化,从源代码中能够看到(虽然我没看懂,应该是使用了通用的方法来建立Promise):web
// Exposing the Promise capabilities var thenExposed = false; for ( var i = 0; i < options.expose.length; i+=1 ) { var method = options.expose[i]; plumbing[ method === 'promise' ? 'exposePromise' : 'exposePromiseMethod' ]( options.request.Request.prototype, null, '_rp_promise', method ); if (method === 'then') { thenExposed = true; } } if (!thenExposed) { throw new Error('Please expose "then"'); }
既然如此,咱们能够构造Promise,交给await。下面就把request
包裹成一个Promise:promise
1 //token.js 2 module.exports.getAccessToken = async (options) => { 3 return new Promise(function (resolve, reject) { 4 request(options, function (error, res, body) { 5 if (!error && res.statusCode == 200) { 6 resolve(body); 7 } else { 8 if(error){ 9 reject(error); 10 }else{ 11 reject(body); 12 } 13 } 14 }); 15 }); 16 }; 17 //app.js 18 (async ()=> { 19 let access = await token.getAccessToken(authoptions).then((value)=>{ 20 //handle value if requires 21 return value; 22 }).catch((error)=>{ 23 return error; 24 }); 25 console.log('access', access); 26 //use token to send the request 27 })();
API成功返回的结果咱们每每须要按需处理,这一步放在then函数中进行。由于Promise调用then仍然是Promise,所以这里链式调用的then和catch。
进一步地,咱们尝试使用内置模块 util
对函数进行promise化,形如:闭包
//token.js const request = require('request'); const {promisify} = require('util'); const requestPromise = promisify(request); module.exports.getAccessToken = async (options) => { return requestPromise(options); }; //app.js (async ()=> { let access = await token.getAccessToken(authoptions).then((value)=>{ //handle value if requires return value; }).catch((error)=>{ return error; }); console.log('access', access); //use token to send the request })();
说了这么多,对我而言,目前最大的收获就是理解了如何使用Promise/async/await,把异步函数顺序执行:把带有闭包的函数包裹进Promise,而后使用async/await执行该Promise。app
好了,以上是我解决此类问题的思路。我相信必然还有其余优雅的解决方式,甚至是最佳实践。今天,借此机会,抛砖引玉,但愿你们可以不吝赐教。异步
最后,容我温习一下Promise相关的内容,有片面的地方请你们指正。
Promise对象: async
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
Promise有三种状态: 初始状态,执行成功,执行出错。 then()表示promise执行后的进一步处理,它能够带两个callback参数:第一个用于promise成功运行后执行,第二个表示promise运行失败后执行。catch()表示promise运行失败后所执行的工做。catch()能够理解为语法糖,当then()的第二个callback参数省略的时候,意味着须要调用catch(由于未处理的失败的promise在未来某个node版本会致使程序退出)。须要注意的是,then()/catch()方法也是返回Promise,所以能够链式调用。