Node.js 8 中的 util.promisify的详解


Posted in Javascript onJune 12, 2017

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 的回调风格,所有函数都可以这样转换。也就是说,满足下面两个条件即可。

  1. 最后一个参数是函数
  2. 回调函数的参数为 (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 当中有大量异步函数。这些异步函数,大多要依赖回调进行处理(这里我觉得把事件侦听算作回调也是合理的),但是回调嵌套层次一多,就会形成所谓的“回调陷阱”,让开发者苦不堪言。

Node.js 8 中的 util.promisify的详解

为了解决这个问题,开发社区经过摸索,总结出来一套名为 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();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 学习第六课 实现一个Ajax的TreeView
May 17 Javascript
原生javascript获取元素样式属性值的方法
Dec 25 Javascript
js读写json文件实例代码
Oct 21 Javascript
js兼容火狐获取图片宽和高的方法
May 21 Javascript
Bootstrap每天必学之表单
Nov 23 Javascript
Bootstrap的Carousel配合dropload.js实现移动端滑动切换图片
Mar 10 Javascript
webpack配置文件和常用配置项介绍
Apr 28 Javascript
jQuery轮播图实例详解
Aug 15 jQuery
apicloud拉起小程序并传递参数的方法示例
Nov 21 Javascript
vue favicon设置以及动态修改favicon的方法
Dec 21 Javascript
JS实现灯泡开关特效
Mar 30 Javascript
javascript将扁平的数据转为树形结构的高效率算法
Feb 27 Javascript
jquery处理checkbox(复选框)是否被选中实例代码
Jun 12 #jQuery
实现微信小程序的wxml文件和wxss文件在webstrom的支持
Jun 12 #Javascript
JavaScript初学者必看“new”
Jun 12 #Javascript
详解vue.js 开发环境搭建最简单攻略
Jun 12 #Javascript
Ionic + Angular.js实现验证码倒计时功能的方法
Jun 12 #Javascript
微信小程序 实现点击添加移除class
Jun 12 #Javascript
JavaScript该如何学习 怎样轻松学习JavaScript
Jun 12 #Javascript
You might like
DOTA2 1月28日更新:监管系统降临刀塔世界
2021/01/28 DOTA
PHP中UNIX时间戳和日期间的转换与计算实例
2014/11/19 PHP
PHP多态代码实例
2015/06/26 PHP
详解php魔术方法(Magic methods)的使用方法
2016/02/14 PHP
详解PHP的Laravel框架中Eloquent对象关系映射使用
2016/02/26 PHP
Yii2.0框架实现带分页的多条件搜索功能示例
2019/02/20 PHP
PHP操作路由器实现方法示例
2019/04/27 PHP
ext form 表单提交数据的方法小结
2008/08/08 Javascript
jquery validator 插件增加日期比较方法
2010/02/21 Javascript
js获取IP和PcName(IE)在vs中可用
2013/08/02 Javascript
JavaScript定义类的几种方式总结
2014/01/06 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
2015/08/21 Javascript
全面解析Bootstrap表单使用方法(表单控件)
2015/11/24 Javascript
Bootstrap入门书籍之(五)导航条、分页导航
2016/02/17 Javascript
jQuery实现点击按钮文字变成input框点击保存变成文字
2016/05/09 Javascript
深入了解JavaScript的逻辑运算符(与、或)
2016/12/20 Javascript
防止重复发送 Ajax 请求
2017/02/15 Javascript
JavaScript关联数组用法分析【概念、定义、遍历】
2017/03/15 Javascript
JavaScript重复元素处理方法分析【统计个数、计算、去重复等】
2017/12/14 Javascript
chosen实现省市区三级联动
2018/08/16 Javascript
angularJS1 url中携带参数的获取方法
2018/10/09 Javascript
Layui弹出层 加载 做编辑页面的方法
2019/09/16 Javascript
jQuery 实现DOM元素拖拽交换位置的实例代码
2020/07/14 jQuery
[37:02]OG vs INfamous 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
pygame游戏之旅 按钮上添加文字的方法
2018/11/21 Python
Python3转换html到pdf的不同解决方案
2019/03/11 Python
python绘制双Y轴折线图以及单Y轴双变量柱状图的实例
2019/07/08 Python
Python 类属性与实例属性,类对象与实例对象用法分析
2019/09/20 Python
在网上学习全世界最好的课程:Coursera
2017/11/07 全球购物
铭立家具面试题
2012/12/06 面试题
副科级后备干部考察材料
2014/05/15 职场文书
小学生我的梦想演讲稿
2014/08/21 职场文书
反腐倡廉影片观后感
2015/06/08 职场文书
高中生军训感言
2015/08/01 职场文书
民间借贷纠纷答辩状
2015/08/03 职场文书
用Python爬虫破解滑动验证码的案例解析
2021/05/06 Python