Node.js8于上月底正式发布,带来了许多新特性。其中一个更值得注意的是util.promisify()方法。如果您已经熟悉Promises,请继续阅读。如果您对Promise不熟悉,可以跳到下一章:Promise简介。util.promisify()尽管Promise已经流行起来,但是在Node.js中仍然有大量依赖回调的异步函数。如果我们把每个功能都封装起来,那就真的很麻烦,甚至更麻烦。所以Node.js8提供了util.promisify()方法,方便我们把原来的异步回调方法改成支持Promise的方法。接下来想继续用.then().then().then()来排队,还是await看实际需要。我们看例子,让读取目录文件状态的fs.stat支持Promise:constutil=require('util');constfs=require('fs');conststat=util.promisify(fs.stat);stat('.').then((stats)=>{//用`stats`做点什么}).catch((error)=>{//处理错误。});那个怎么样?简单吧?根据文档,只要符合Node.js的回调风格,所有的函数都可以这样转换。也就是说,只要满足下面两个条件,不管是不是native方法:最后一个参数是回调函数。回调函数的参数是(err,result),前面是可能的错误,后面是正常的结果结合Await/Async使用同上的例子,如果要结合Await/Async,可以使用它是这样的:constutil=require('util');constfs=require('fs');conststat=util.promisify(fs.stat);asyncfunctionreadStats(dir){try{letstats=awaitstat(dir);//使用`stats`做一些事情}catch(err){//处理错误。安慰。日志(错误);}}readStats('.');自定义Promise处理函数如果现有的回调函数不符合这种风格,那还能用util.promisify()吗?答案是肯定的。我们只需要在函数中添加一个属性util.promisify.custom,指定一个函数作为Promise处理函数即可。请看下面的代码:constutil=require('util');//这是要使用回调函数处理的函数doSomething(foo,callback){//...}//给它添加一个方法,使用来调用doSomething[util.promisify.custom]=function(foo){//自定义生成Promise的逻辑returngetPromiseSomehow();};constpromisified=util.promisify(doSomething);console.log(promisified===doSomething[util.promisify.custom]);//prints'true'这样,每当我们承诺目标函数doSomething时,我们将获取先前定义的函数。运行它会根据我们设计的具体逻辑返回Promise实例。我们可以升级所有以前的异步回调函数。Promise简介由于各种历史原因,JS中有大量的异步功能。这些异步函数大多依赖回调进行处理(这里我觉得将事件监听算作回调是合理的),但是如果回调嵌套的层次太多,就会形成所谓的“回调陷阱”,让开发者悲惨的。为了解决这个问题,开发社区摸索总结出了一套解决方案,叫做Promise/A+。总的来说,该方案将原有的回调函数用一个“Promise回调实例”进行包装,可以将原有复杂的嵌套进行扩展和扁平化,从而降低开发和维护的难度和成本。newPromise((resolve,reject)=>{//构建一个Promise实例someAsyncFunction((err,result)=>{//调用原来的异步函数if(err){//发生错误,进入错误处理模式returnreject(err);}resolve(result);//一切正常,转到队列中的下一个链接});}).then(result=>{//下一个链接returndoSomething(result);}).then(result2=>{//另一个链接returndoSomething2(result2);})...//各种中间链接。catch(err=>{//错误处理console.log(err);});ES2015(ES6)包含了Promise标准,现在大部分运行时都实现了,我们可以放心使用。而且,由于Promises不需要新的语法元素,因此即使在不支持原生Promises的环境中也可以使用库,例如??Q或Bluebird,甚至是jQuery。在小程序中同样有效!ES2017增加了Await/Async语法,但请注意Await后面必须跟一个Promise实例才能实现异步。所以,大家要好好学习Promise的概念!functionresolveAfter2Seconds(x){returnnewPromise(resolve=>{setTimeout(()=>{resolve(x);},2000);});}asyncfunctionf1(){varx=awaitresolveAfter2Seconds(10);控制台日志(x);//10}f1();该示例来自MDN。如果你想深入了解Promise的使用,强烈推荐这篇分享:Promise的N种用法。它可以帮助您一站式学习使用Promise。PS2:刚看到Node.js已经发布8.1了,好快啊。。。新版本的Changelog来了,主要是修复。延伸阅读:Node.jsv8官方文档官方文档自定义Promise处理函数中的util.promisify()同步发布于我的博客
