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 面向对象,实现namespace,class,继承,重载
Oct 29 Javascript
详细讲解JS节点知识
Jan 31 Javascript
js 数值转换为3位逗号分隔的示例代码
Feb 19 Javascript
Jquery仿IGoogle实现可拖动窗口示例代码
Aug 22 Javascript
基于HTML模板和JSON数据的JavaScript交互(移动端)
Apr 06 Javascript
基于JQuery的$.ajax方法进行异步请求导致页面闪烁的解决办法
May 10 Javascript
vue的Virtual Dom实现snabbdom解密
May 03 Javascript
bootstrap table插件的分页与checkbox使用详解
Jul 23 Javascript
微信小程序开发问题之wx.previewImage
Dec 25 Javascript
关于ckeditor在bootstrap中modal中弹框无法输入的解决方法
Sep 11 Javascript
使用 JavaScript 创建并下载文件(模拟点击)
Oct 25 Javascript
Vue单页面应用中实现Markdown渲染
Feb 14 Vue.js
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 CLI实现简单的数据库实时监控调度
2009/07/01 PHP
简单实用的网站PHP缓存类实例
2014/07/18 PHP
php生成PDF格式文件并且加密
2015/06/22 PHP
Thinkphp单字母函数使用指南
2016/05/08 PHP
php str_getcsv把字符串解析为数组的实现方法
2017/04/05 PHP
PHP利用Cookie设置用户30分钟未操作自动退出功能
2017/07/03 PHP
图片自动更新(说明)
2006/10/02 Javascript
jQuery使用append在html元素后同时添加多项内容的方法
2015/03/26 Javascript
jQuery时间插件jquery.clock.js用法实例(5个示例)
2016/01/14 Javascript
JS闭包用法实例分析
2017/03/27 Javascript
js获取文件里面的所有文件名(实例)
2017/10/17 Javascript
thinkjs 文件上传功能实例代码
2017/11/08 Javascript
js判断数组是否包含某个字符串变量的实例
2017/11/24 Javascript
JavaScript循环遍历你会用哪些之小结篇
2018/09/28 Javascript
Vue中的methods、watch、computed的区别
2018/11/26 Javascript
layui 数据表格 点击分页按钮 监听事件的实例
2019/09/02 Javascript
使用VScode 插件debugger for chrome 调试react源码的方法
2019/09/13 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
JS实现简单移动端鼠标拖拽
2020/07/23 Javascript
微信小程序对图片进行canvas压缩的方法示例详解
2020/11/12 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
python在windows命令行下输出彩色文字的方法
2015/03/19 Python
Python multiprocessing模块中的Pipe管道使用实例
2015/04/11 Python
python适合人工智能的理由和优势
2019/06/28 Python
对django中foreignkey的简单使用详解
2019/07/28 Python
几款主流好用的富文本编辑器(所见即所得常用编辑器)介绍
2021/03/17 Javascript
乔丹诺(Giordano)酒庄德国官网:找到最好的意大利葡萄酒
2017/12/28 全球购物
全球工业:Global Industrial
2020/02/01 全球购物
护理专业应届毕业生推荐信
2013/11/15 职场文书
优秀本科生求职推荐信
2014/02/24 职场文书
敬老院活动总结
2014/04/28 职场文书
语文高效课堂实施方案
2014/05/03 职场文书
2015年学校教务处工作总结
2015/05/11 职场文书
幼儿教师继续教育培训心得体会
2016/01/19 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
Pygame Event事件模块的详细示例
2021/11/17 Python