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在线html(富文本,所见即所得)编辑器
Dec 18 Javascript
Jquery chosen动态设置值实例介绍
Aug 08 Javascript
图片动画横条广告带上下滚动可自定义图片、链接等等
Oct 20 Javascript
javascript框架设计读书笔记之模块加载系统
Dec 02 Javascript
JavaScript通过字符串调用函数的实现方法
Mar 18 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
Mar 08 Javascript
在vue中通过axios异步使用echarts的方法
Jan 13 Javascript
如何用input标签和jquery实现多图片的上传和回显功能
May 16 jQuery
js计时事件实现圆形时钟
Mar 25 Javascript
使用preload预加载页面资源时注意事项
Feb 03 Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
May 01 Javascript
JS变量提升及函数提升实例解析
Sep 03 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文件去掉PHP注释空格的函数分析(PHP代码压缩)
2013/07/02 PHP
smarty简单分页的实现方法
2014/10/27 PHP
thinkphp中html:list标签传递多个参数实例
2014/10/30 PHP
PIGCMS 如何关闭聊天机器人
2015/02/12 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
2017/11/14 PHP
javascript数组去重3种方法的性能测试与比较
2013/03/26 Javascript
js单例模式详解实例
2013/11/21 Javascript
禁用Enter键表单自动提交实现代码
2014/05/22 Javascript
jquery实现的缩略图预览滑块实例
2015/06/25 Javascript
javascript+ajax实现产品页面加载信息
2015/07/09 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
2015/12/07 Javascript
使用base64对图片的二进制进行编码并用ajax进行显示
2017/01/03 Javascript
vue分类筛选filter方法简单实例
2017/03/30 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
2017/09/18 Javascript
微信小程序之选项卡的实现方法
2017/09/29 Javascript
如何以Angular的姿势打开Font-Awesome详解
2018/04/22 Javascript
原生JS实现的雪花飘落动画效果
2018/05/03 Javascript
vue中在vuex的actions中请求数据实例
2019/11/08 Javascript
vue之延时刷新实例
2019/11/14 Javascript
Antd-vue Table组件添加Click事件,实现点击某行数据教程
2020/11/17 Javascript
Python正则表达式匹配ip地址实例
2014/10/09 Python
python编程开发之textwrap文本样式处理技巧
2015/11/13 Python
详解tensorflow训练自己的数据集实现CNN图像分类
2018/02/07 Python
Python JSON格式数据的提取和保存的实现
2019/03/22 Python
用Python开发app后端有优势吗
2020/06/29 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
2021/01/30 Python
html5 学习简单的拾色器
2010/09/03 HTML / CSS
函授毕业自我鉴定
2014/02/04 职场文书
大学生村官座谈会发言材料
2014/05/25 职场文书
十佳家长事迹材料
2014/08/26 职场文书
2015年八一建军节活动总结
2015/03/20 职场文书
红高粱观后感
2015/06/10 职场文书
公文格式,规则明细(新手收藏)
2019/07/23 职场文书
springboot如何初始化执行sql语句
2021/06/22 Java/Android
SQL Server代理:理解SQL代理错误日志处理方法
2021/06/30 SQL Server
为什么MySQL分页用limit会越来越慢
2021/07/25 MySQL