Node.js 8 中的 util.promisify的详解

Node.js 8带来了 不少新特性 。其中比较值得注意的,便有 util.promisify() 这个方法。node

util.promisify()git

虽然 Promise 已经普及,可是 Node.js 里仍然有大量的依赖回调的异步函数,若是咱们每一个函数都封装一次,还麻烦。github

因此 Node8 就提供了 util.promisify() 这个方法,方便咱们快捷的把原来的异步回调方法改为返回 Promise 实例的方法,接下来,想继续用队列,仍是 await 就看须要了。小程序

例如 读取文件状态的操做:promise

var fs = require("fs");
 //读取文件的状态;
 fs.stat(path,callback);异步

fs.stat("./wenjian.txt",function(err,stats){
    console.log(err);
    console.log(stats);
//    获取文件的大小;
    console.log(stats.size);
//    获取文件最后一次访问的时间;
    console.log(stats.atime.toLocaleString());
//    文件建立的时间;
    console.log(stats.birthtime.toLocaleString());
//    文件最后一次修改时间;
    console.log(stats.mtime.toLocaleString());
//    状态发生变化的时间;
    console.log(stats.ctime.toLocaleString())
//判断是不是目录;是返回true;不是返回false;
    console.log(stats.isFile())
//    判断是不是文件;是返回true、不是返回false;
    console.log(stats.isDirectory())
})  

将读取文件状态的回调函数经过util来promise化:async

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('./path').then((stats) => {
  // Do something with `stats`
 }).catch((error) => {
  // Handle the error.
 });

 

只要符合 Node.js 的回调风格,全部函数均可以这样转换。也就是说,知足下面两个条件便可。函数

  1. 最后一个参数是函数
  2. 回调函数的参数为 (err, result),前面是可能的错误,后面是正常的结果

结合 Await/Async 使用ui

一样是上面的例子,若是想要结合 Await/Async,能够这样使用:spa

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('./path');  //调用

自定义 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 当中有大量异步函数。这些异步函数,大多要依赖回调进行处理(这里我以为把事件侦听算做回调也是合理的),可是回调嵌套层次一多,就会造成所谓的“回调陷阱”,让开发者苦不堪言。

 为了解决这个问题,开发社区通过摸索,总结出来一套名为 Promise/A+ 的解决方案。大致上来讲,这套方案经过使用 “Promise 回调实例”包裹原先的回调函数,能够将原先复杂的嵌套展开、铺平,从而下降开发和维护的难度和成本。

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();

 

 原文

相关文章
相关标签/搜索