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实现多域名不同文件的调用方法
Jan 12 Javascript
20个非常棒的 jQuery 幻灯片插件和教程分享
Aug 23 Javascript
HTML Color Picker(js拾色器效果)
Aug 27 Javascript
jquery实现倒计时代码分享
Jun 13 Javascript
AngularJS基础 ng-csp 指令详解
Aug 01 Javascript
浅谈js中StringBuffer类的实现方法及使用
Sep 02 Javascript
微信小程序之数据双向绑定与数据操作
May 12 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
Jun 23 Javascript
JavaScrip关于创建常量的知识点
Dec 07 Javascript
详解在vue-cli中使用graphql即vue-apollo的用法
Sep 08 Javascript
vue模式history下在iis中配置流程
Apr 17 Javascript
fastadmin中调用js的方法
May 14 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实现的百度搜索某地天气的小偷代码
2014/04/23 PHP
2014年10个最佳的PHP图像操作库
2014/07/14 PHP
php支付宝接口用法分析
2015/01/04 PHP
php实现专业获取网站SEO信息类实例
2015/04/02 PHP
PHP设计模式之迭代器模式
2016/06/17 PHP
Javascript操纵Cookie实现购物车程序
2007/02/15 Javascript
JS trim去空格的最佳实践
2011/10/30 Javascript
Javascript Boolean、Nnumber、String 强制类型转换的区别详细介绍
2012/12/13 Javascript
JavaScript获取onclick、onchange等事件值的代码
2013/07/22 Javascript
JQuery对class属性的操作实现按钮开关效果
2013/10/11 Javascript
JavaScript操作HTML元素和样式的方法详解
2015/10/21 Javascript
JS数组排序技巧汇总(冒泡、sort、快速、希尔等排序)
2015/11/24 Javascript
ECharts仪表盘实例代码(附源码下载)
2016/02/18 Javascript
JavaScript判断数字是否为质数的方法汇总
2016/06/02 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
IntelliJ IDEA 安装vue开发插件的方法
2017/11/21 Javascript
angularjs实现table增加tr的方法
2018/02/27 Javascript
浅谈node中的cluster集群
2018/06/02 Javascript
详解写好JS条件语句的5条守则
2019/02/28 Javascript
vue实现文字横向无缝走马灯组件效果的实例代码
2019/04/09 Javascript
vue请求本地自己编写的json文件的方法
2019/04/25 Javascript
如何HttpServletRequest文件对象并储存
2020/08/14 Javascript
python实现连接mongodb的方法
2015/05/08 Python
Python中动态创建类实例的方法
2017/03/24 Python
Python高级特性与几种函数的讲解
2019/03/08 Python
使用python 写一个静态服务(实战)
2019/06/28 Python
python实现MySQL指定表增量同步数据到clickhouse的脚本
2021/02/26 Python
美国五金商店:Ace Hardware
2018/03/27 全球购物
欧洲领先的火车票和大巴票预订平台:Trainline
2018/12/26 全球购物
是否可以从一个static方法内部发出对非static方法的调用?
2014/08/18 面试题
工厂保洁员岗位职责
2013/12/04 职场文书
设计专业毕业生求职信
2014/06/25 职场文书
2014年学校食堂工作总结
2014/11/25 职场文书
干部考核工作总结
2015/08/12 职场文书
高端收音机+蓝牙音箱,JBL TUNER FM带收音蓝牙音箱评测
2021/04/24 无线电
微软官方消息,在 2023 年 4 月 11 日之后微软将不再为 Office 2013 和 Skype for Business 2015 提供安全更新
2022/04/21 数码科技