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 相关文章推荐
JS 时间显示效果代码
Aug 23 Javascript
jquery ready()的几种实现方法小结
Jun 18 Javascript
JS小功能(checkbox实现全选和全取消)实例代码
Nov 28 Javascript
js 左右悬浮对联广告特效代码
Dec 12 Javascript
理解javascript中的with关键字
Feb 15 Javascript
AngularJS中使用HTML5手机摄像头拍照
Feb 22 Javascript
JS图片等比例缩放方法完整示例
Aug 03 Javascript
基于js实现的限制文本框只可以输入数字
Dec 05 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
Jan 24 Javascript
关于Vue实现组件信息的缓存问题
Aug 23 Javascript
p5.js绘制旋转的正方形
Oct 23 Javascript
微信小程序的引导页实现代码
Jun 24 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
php xml文件操作实现代码(二)
2009/03/20 PHP
理解PHP中的stdClass类
2014/04/18 PHP
学习php设计模式 php实现命令模式(command)
2015/12/08 PHP
Yii2实现增删改查后留在当前页的方法详解
2017/01/13 PHP
PHP静态方法和静态属性及常量属性的区别与介绍
2019/03/22 PHP
laravel使用数据库测试注意事项
2020/04/10 PHP
jquery 表单进行客户端验证demo
2009/08/24 Javascript
Javascript改变CSS样式(局部和全局)
2013/12/18 Javascript
jquery append()方法与html()方法的区别及使用介绍
2014/08/01 Javascript
PHP中CURL的几个经典应用实例
2015/01/23 Javascript
js中setTimeout()与clearTimeout()用法实例浅析
2015/05/12 Javascript
JavaScript中模拟实现jsonp
2015/06/19 Javascript
MVC Ajax Helper或Jquery异步加载部分视图
2015/11/29 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
jQuery使用zTree插件实现可拖拽的树示例
2017/09/23 jQuery
基于JavaScript实现一个简单的Vue
2018/09/26 Javascript
Vue和React组件之间的传值方式详解
2019/01/31 Javascript
新手入门带你学习JavaScript引擎运行原理
2019/06/24 Javascript
[04:59]DOTA2-DPC中国联赛 正赛 Ehome vs iG 选手采访
2021/03/11 DOTA
Python实现身份证号码解析
2015/09/01 Python
Python温度转换实例分析
2018/01/17 Python
tensorflow 输出权重到csv或txt的实例
2018/06/14 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
Appium+python自动化怎么查看程序所占端口号和IP
2019/06/14 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
python 获取谷歌浏览器保存的密码
2021/01/06 Python
卡骆驰英国官网:Crocs英国
2019/08/22 全球购物
出售房屋委托书范本
2014/09/24 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书
行政上诉状范文
2015/05/23 职场文书
刑事法律意见书
2015/06/04 职场文书
永远是春天观后感
2015/06/12 职场文书
七年级作文之雪景
2019/11/18 职场文书
Javascript 解构赋值详情
2021/11/17 Javascript
怎么禁用Windows 11快照布局? win11不使用快照布局的技巧
2021/11/21 数码科技
零基础学java之循环语句的使用
2022/04/10 Java/Android