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将文本转化成JSON对象需要注意的问题
May 09 Javascript
JS实现时间格式化的方式汇总
Oct 16 Javascript
js判断页面中是否有指定控件的简单实例
Mar 04 Javascript
AngularJs基本特性解析(一)
Jul 21 Javascript
jQuery子元素过滤选择器用法示例
Sep 09 Javascript
使用JavaScript实现链表的数据结构的代码
Aug 02 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
Oct 17 Javascript
spirngmvc js传递复杂json参数到controller的实例
Mar 29 Javascript
vue如何解决循环引用组件报错的问题
Sep 22 Javascript
Vue.js 事件修饰符的使用教程
Nov 01 Javascript
Nuxt.js的路由跳转操作(页面跳转nuxt-link)
Nov 06 Javascript
微信小程序 接入腾讯地图的两种写法
Jan 12 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
SUN的《AJAX与J2EE》全文译了
2007/02/23 Javascript
JavaScript 编程引入命名空间的方法与代码
2007/08/13 Javascript
JQuery 获得绝对,相对位置的坐标方法
2010/02/09 Javascript
基于jQuery的表格操作插件
2010/04/22 Javascript
jquery attr 设定src中含有&(宏)符号问题的解决方法
2011/07/26 Javascript
jquery中ajax学习笔记3
2011/10/16 Javascript
浅析JQuery获取和设置Select选项的常用方法总结
2013/07/04 Javascript
javascript生成随机颜色示例代码
2014/05/05 Javascript
jquery 按键盘上的enter事件
2014/05/11 Javascript
Javascript的&&和||的另类用法
2014/07/23 Javascript
jQuery实现的手机发送验证码倒计时效果代码分享
2015/08/24 Javascript
js获取鼠标点击的对象,点击另一个按钮删除该对象的实现代码
2016/05/13 Javascript
jQuery获取访问者IP地址的方法(基于新浪API与QQ查询接口)
2016/05/25 Javascript
KnockoutJS 3.X API 第四章之数据控制流foreach绑定
2016/10/10 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
详解nodejs异步I/O和事件循环
2017/06/07 NodeJs
微信小程序三级联动地址选择器的实例代码
2017/07/12 Javascript
vue使用localStorage保存登录信息 适用于移动端、PC端
2019/05/27 Javascript
基于Nuxt.js项目的服务端性能优化与错误检测(容错处理)
2019/10/23 Javascript
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
Python Property属性的2种用法
2015/06/21 Python
Python编程之Re模块下的函数介绍
2017/10/28 Python
matplotlib savefig 保存图片大小的实例
2018/05/24 Python
Python中函数的基本定义与调用及内置函数详解
2019/05/13 Python
python3 打印输出字典中特定的某个key的方法示例
2019/07/06 Python
django基于存储在前端的token用户认证解析
2019/08/06 Python
Python 根据日志级别打印不同颜色的日志的方法示例
2019/08/08 Python
python实现从ftp上下载文件的实例方法
2020/07/19 Python
美国酒店控股公司:Choice Hotels
2018/06/15 全球购物
基层干部2014全国两会学习心得体会
2014/03/10 职场文书
民主评议党员自我评价材料
2014/09/18 职场文书
房屋租赁合同解除协议书
2014/10/11 职场文书
见习期个人总结
2015/03/05 职场文书
2019最新版试用期劳动合同模板!
2019/07/04 职场文书
Python list去重且保持原顺序不变的方法
2021/04/03 Python
vue @ ~ 相对路径 路径别名设置方式
2022/06/05 Vue.js