Node.js 8 中的 util.promisify的详解
node.js 8 于上个月月底正式发布,带来了 很多新特性 。其中比较值得注意的,便有 util.promisify() 这个方法。
util.promisify()
虽然 promise 已经普及,但是 node.js 里仍然有大量的依赖回调的异步函数,如果我们每个函数都封装一次,也是齁麻烦齁麻烦的,比齁还麻烦。
所以 node8 就提供了 util.promisify() 这个方法,方便我们快捷的把原来的异步回调方法改成返回 promise 实例的方法,接下来,想继续用队列,还是 await 就看需要了。
我们看下范例:
const util = require('util'); const fs = require('fs'); const stat = util.promisify(fs.stat); stat('.') .then((stats) => { // do something with `stats` }) .catch((error) => { // handle the error. });
怎么样,很简单吧?按照文档中的说法,只要符合 node.js 的回调风格,所有函数都可以这样转换。也就是说,满足下面两个条件即可。
- 最后一个参数是函数
- 回调函数的参数为 (err, result),前面是可能的错误,后面是正常的结果
结合 await/async 使用
同样是上面的例子,如果想要结合 await/async,可以这样使用:
const util = require('util'); const fs = require('fs'); const stat = util.promisify(fs.stat); async function readstats(dir) { try { let stats = await stat(dir); // do something with `stats` } catch (err) { // handle the error. console.log(err); } } readstats('.');
自定义 promise 化处理函数
那如果函数不符合这个风格,还能用 util.promisify() 么?答案也是肯定的。我们只要给函数增加一个属性,util.promisify.custom
,指定一个函数作为 promise 化处理函数,即可。请看下面的代码:
const util = require('util'); function dosomething(foo, callback) { // ... } dosomething[util.promisify.custom] = function(foo) { return getpromisesomehow(); }; const promisified = util.promisify(dosomething); console.log(promisified === dosomething[util.promisify.custom]); // prints 'true'
如此一来,任何时候我们对目标函数 dosomething 进行 promise 化处理,都会得到之前定义的函数。运行它,就会按照我们设计的特定逻辑返回 promise 实例。
我们就可以升级以前所有的异步回调函数了。
promise 介绍
因为种种历史原因,js 当中有大量异步函数。这些异步函数,大多要依赖回调进行处理(这里我觉得把事件侦听算作回调也是合理的),但是回调嵌套层次一多,就会形成所谓的“回调陷阱”,让开发者苦不堪言。
为了解决这个问题,开发社区经过摸索,总结出来一套名为 promise/a+ 的解决方案。大体上来说,这套方案通过使用 “promise 回调实例”包裹原先的回调函数,可以将原先复杂的嵌套展开、铺平,从而降低开发和维护的难度和成本。
new promise( (resolve, reject) => { // 构建一个 promise 实例 someasyncfunction( (err, result) => { // 调用原来的异步函数 if (err) { // 发生错误,进入错误处理模式 return reject(err); } resolve(result); // 一切正常,进入队列的下一环节 }); }) .then( result => { // 下一环节 return dosomething(result); }) .then( result2 => { // 又下一环节 return dosomething2(result2); }) ... // 各种中间环节 .catch( err => { // 错误处理 console.log(err); });
es2015(es6)里包含了 promise 标准,如今已经在大部分运行时里实装,我们可以放心大胆的使用它。而且,由于 promise 不需要新的语法元素,所以即使在不支持原生 promise 的环境里也可以使用类库,比如 q 或者 bluebird ,甚至 jquery 。
在小程序里也有效哟。
es2017 增加了 await/async 语法,但请注意, await 后面必须跟 promise 实例才能实现异步。所以,大家还是把 promise 的概念学好吧!
function resolveafter2seconds(x) { return new promise(resolve => { settimeout(() => { resolve(x); }, 2000); }); } async function f1() { var x = await resolveafter2seconds(10); console.log(x); // 10 } f1();
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: ajax请求data遇到的问题分析