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 相关文章推荐
通过url查找a元素应用案例
Apr 29 Javascript
JavaScript中的Math.sin()方法使用详解
Jun 15 Javascript
如何解决谷歌浏览器下jquery无法获取图片的尺寸
Sep 10 Javascript
JavaScritp添加url参数并将参数加入到url中及更改url参数的方法
Oct 26 Javascript
老生常谈javascript的类型转换
Oct 12 Javascript
JS判断是否为JSON对象及是否存在某字段的方法(推荐)
Nov 29 Javascript
js实现的简练高效拖拽功能示例
Dec 21 Javascript
原生Javascript插件开发实践
Jan 18 Javascript
微信小程序如何获取用户手机号
Jan 26 Javascript
js实现限定区域范围拖拉拽效果
Nov 20 Javascript
实用的 vue tags 创建缓存导航的过程实现
Dec 03 Vue.js
vue实现树状表格效果
Dec 29 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
mysql5的sql文件导入到mysql4的方法
2008/10/19 PHP
php使用Cookie实现和用户会话的方法
2015/01/21 PHP
浅谈socket同步和异步、阻塞和非阻塞、I/O模型
2016/12/15 PHP
详解PHP中的 input属性(隐藏 只读 限制)
2017/08/14 PHP
详解php语言最牛掰的Laravel框架
2017/11/20 PHP
javawscript 三级菜单的实现原理
2009/07/01 Javascript
jQuery contains过滤器实现精确匹配使用方法
2013/04/12 Javascript
jQuery实现的登录浮动框效果代码
2015/09/26 Javascript
vue 数组和对象不能直接赋值情况和解决方法(推荐)
2017/10/25 Javascript
js登录滑动验证的实现(不滑动无法登陆)
2018/01/03 Javascript
使用Angular CLI生成 Angular 5项目教程详解
2018/03/18 Javascript
vue.js 实现输入框动态添加功能
2018/06/25 Javascript
vue3.0 CLI - 2.2 - 组件 home.vue 的初步改造
2018/09/14 Javascript
vue轻量级框架无法获取到vue对象解决方法
2019/05/12 Javascript
多个vue子路由文件自动化合并的方法
2019/09/03 Javascript
[03:01]2014DOTA2国际邀请赛 DC:我是核弹粉,为Burning和国土祝福
2014/07/13 DOTA
[47:20]DAC2018 4.4 淘汰赛 Optic vs Mineski 第一场
2018/04/05 DOTA
[01:07:41]IG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
跟老齐学Python之深入变量和引用对象
2014/09/24 Python
python学习 流程控制语句详解
2016/06/01 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
用Pelican搭建一个极简静态博客系统过程解析
2019/08/22 Python
pd.DataFrame统计各列数值多少的实例
2019/12/05 Python
PyTorch中反卷积的用法详解
2019/12/30 Python
Python3批量创建Crowd用户并分配组
2020/05/20 Python
Python基于pandas绘制散点图矩阵代码实例
2020/06/04 Python
通过实例简单了解Python sys.argv[]使用方法
2020/08/04 Python
基于Django快速集成Echarts代码示例
2020/12/01 Python
 Alo Yoga官网:购买瑜伽服装
2018/06/17 全球购物
Senreve官网:美国旧金山的奢侈手袋品牌
2019/03/21 全球购物
serialVersionUID具有什么样的特征
2014/02/20 面试题
行政人事岗位职责
2014/03/17 职场文书
高职教师先进事迹材料
2014/08/24 职场文书
同意迁入证明模板
2014/10/26 职场文书
2014年法院工作总结
2014/11/24 职场文书
python数字图像处理之图像的批量处理
2022/06/28 Python