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实现页面打印的三种方法
Mar 05 Javascript
利用Js的console对象,在控制台打印调式信息测试Js的实现
Nov 26 Javascript
js实现本地时间同步功能
Aug 26 Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
Sep 18 Javascript
nuxt+axios解决前后端分离SSR的示例代码
Oct 24 Javascript
vue-cli3+typescript初体验小结
Feb 28 Javascript
原生js通过一行代码实现简易轮播图
Jun 05 Javascript
es6中比较有用的7个技巧小结
Jul 12 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 Javascript
Vue单文件组件开发实现过程详解
Jul 30 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
Jan 15 Javascript
使用Ajax实现无刷新上传文件
Apr 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
PHP检测移动设备类mobile detection使用实例
2014/04/14 PHP
Netbeans 8.2将支持PHP7 更精彩
2016/06/13 PHP
Laravel5中防止XSS跨站攻击的方法
2016/10/10 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
PHP中递归的实现实例详解
2017/11/14 PHP
thinkPHP+LayUI 流加载实现功能
2019/09/27 PHP
php实现简易计算器
2020/08/28 PHP
各种常用浏览器getBoundingClientRect的解析
2009/05/21 Javascript
nodejs中简单实现Javascript Promise机制的实例
2014/12/06 NodeJs
jQuery中:reset选择器用法实例
2015/01/04 Javascript
angularjs实现猜数字大小功能
2020/05/20 Javascript
浅谈如何使用webpack构建多页面应用
2018/05/30 Javascript
vue下拉菜单组件(含搜索)的实现代码
2018/11/25 Javascript
React 使用recharts实现散点地图的示例代码
2018/12/07 Javascript
在vue中动态添加class类进行显示隐藏实例
2019/11/09 Javascript
深入解析Python中的list列表及其切片和迭代操作
2016/03/13 Python
python和pygame实现简单俄罗斯方块游戏
2021/02/19 Python
解决python中遇到字典里key值为None的情况,取不出来的问题
2018/10/17 Python
Python 通过调用接口获取公交信息的实例
2018/12/17 Python
jupyter notebook读取/导出文件/图片实例
2020/04/16 Python
详解python tkinter包获取本地绝对路径(以获取图片并展示)
2020/09/04 Python
python开发一个解析protobuf文件的简单编译器
2020/11/17 Python
Python爬虫之Selenium实现键盘事件
2020/12/04 Python
CSS3中的Transition过度与Animation动画属性使用要点
2016/05/20 HTML / CSS
HTML5进度条特效
2014/12/18 HTML / CSS
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
设计模式的基本要素是什么
2014/04/21 面试题
中职生自我鉴定范文
2013/10/03 职场文书
《问银河》教学反思
2014/02/19 职场文书
环保建议书
2014/03/12 职场文书
银行竞聘演讲稿
2014/05/16 职场文书
财务负责人任命书
2014/06/06 职场文书
司法局群众路线教育实践活动开展情况总结
2014/10/25 职场文书
2014年培训工作总结范文
2014/11/27 职场文书
作文之亲情600字
2019/09/23 职场文书
Kubernetes部署实例并配置Deployment、网络映射、副本集
2022/04/01 Servers