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 相关文章推荐
JavaScript访问样式表代码
Oct 15 Javascript
js数组去重的常用方法总结
Jan 24 Javascript
JavaScript版的TwoQueues缓存模型
Dec 29 Javascript
jQuery的bind()方法使用详解
Jul 15 Javascript
jQuery实现的多级下拉菜单效果代码
Aug 24 Javascript
jQuery+css实现的tab切换标签(兼容各浏览器)
Jan 28 Javascript
简述JavaScript提交表单的方式 (Using JavaScript Submit Form)
Mar 18 Javascript
angular4强制刷新视图的方法
Oct 09 Javascript
node基于async/await对mysql进行封装
Jun 20 Javascript
vue基于v-charts封装双向条形图的实现代码
Dec 09 Javascript
小程序实现背景音乐播放和暂停
Jun 19 Javascript
vue-以文件流-blob-的形式-下载-导出文件操作
Aug 07 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
模拟OICQ的实现思路和核心程序(二)
2006/10/09 PHP
php根据日期判断星座的函数分享
2014/02/13 PHP
php使用timthumb生成缩略图的方法
2016/01/22 PHP
php-7.3.6 编译安装过程
2020/02/11 PHP
加载远程图片时,经常因为缓存而得不到更新的解决方法(分享)
2013/06/26 Javascript
JS实现带圆弧背景渐变效果的导航菜单代码
2015/10/13 Javascript
学习JavaScript设计模式之单例模式
2016/01/19 Javascript
JavaScript必知必会(五) eval 的使用
2016/06/08 Javascript
JavaScript实现时间倒计时跳转(推荐)
2016/06/28 Javascript
基于vue的短信验证码倒计时demo
2017/09/13 Javascript
vue-router3.0版本中 router.push 不能刷新页面的问题
2018/05/10 Javascript
nodejs基础之buffer缓冲区用法分析
2018/12/26 NodeJs
Promise扫盲贴
2019/06/24 Javascript
js实现mp3录音通过websocket实时传送+简易波形图效果
2020/06/12 Javascript
详解JavaScript数据类型和判断方法
2020/09/04 Javascript
vue实现下拉菜单树
2020/10/22 Javascript
pyqt4教程之widget使用示例分享
2014/03/07 Python
Python的subprocess模块总结
2014/11/07 Python
Python中的True,False条件判断实例分析
2015/01/12 Python
Python命令行参数解析模块getopt使用实例
2015/04/13 Python
利用Python中SocketServer 实现客户端与服务器间非阻塞通信
2016/12/15 Python
Python 生成 -1~1 之间的随机数矩阵方法
2018/08/04 Python
浅谈Python traceback的优雅处理
2018/08/31 Python
python中正则表达式与模式匹配
2019/05/07 Python
PyQt5的PyQtGraph实践系列3之实时数据更新绘制图形
2019/05/13 Python
使用python写一个自动浏览文章的脚本实例
2019/12/05 Python
《小石潭记》教学反思
2014/02/13 职场文书
文秘专业应届生求职信
2014/05/26 职场文书
教师优秀党员事迹材料
2014/08/14 职场文书
中华魂放飞梦想演讲稿
2014/08/26 职场文书
诚信承诺书
2015/01/19 职场文书
年会邀请函范文
2015/01/30 职场文书
刑事撤诉申请书
2015/05/18 职场文书
战友聚会致辞
2015/07/28 职场文书
会计专业自荐信范文
2019/05/22 职场文书
SQL Server远程连接的设置步骤(图文)
2022/03/23 SQL Server