文档 www.npmjs.com/package/blu…
安装 npm install bluehird
Promisify
简单用法
let fs = require('fs');
let bluebird = require('bluebird');
let read = bluebird.promisify(fs.readFile);
read('1.txt','utf-8').then(function(data){
console.log(data);
})
复制代码
上例,用bluebird的promisify方法,将fs中的readFile方法promise化,也就是说,read方法执行后,会返回一个promise,可以调用then方法执行成功的回调或失败的回调
promisify就是在将readFile包装成一个promise,并处理了readFile的回调方法,下面这段代码可以帮助理解它是怎么做到的
一个promisify的实现
function promisify(fn) {
return function (...args) {
return new Promise(function (resolve, reject) {
fn(...args, function (err, data) {
if (err) reject(err);
resolve(data);
})
})
}
}
复制代码
promisify化后,案例中read即为return的函数,当read执行时,new了一个promise,同时fn也会执行,这里也就是readFile方法会执行,readFile的参数即read调用时传进来的参数,readFile成功时,调用promise的resolve,失败时调用reject,这样就将readFile包装成了一个promise
PromisifyAll
promisifyAll(fs); //就是将fs中所有的方法全部增加一个promise化的方法
promisifyAll的简单实现
function promisifyAll(obj) {
Object.keys(obj).forEach(key => { // es5将对象转化成数组的方法
if (typeof obj[key] === 'function') {
obj[key + 'Async'] = promisify(obj[key])
}
})
}
复制代码
将fs库中所有的方法名都加上Async后缀
比如readFile,会增加一个readFileAsync的方法,这个方法就是promisify化的readFile
第一个用法也可以写为
let fs = require('fs');
promisifyAll(fs); //或用bluebird提供的promisifyAll接口
fs.readFileAsync('1.txt', 'utf8').then(function (data) {
console.log(data);
});
复制代码
那么实际应用中,一个方法满足这几个条件,可以被promisify化
- 该方法必须包含回调函数
- 回调函数必须执行
- 回到函数第一个参数代表err信息,第二个参数代表成功返回的结果
当A、B、C、D四个异步执行方法,B的执行依赖A的执行结果,C的执行依赖B的执行结果,那我们之前会用A嵌套B,B嵌套C,C嵌套D的写法
现在可以将每个异步方法promisify化为promiseA、promiseB、promiseC、promiseD,最后通过promise链式调用,确保顺序执行
promiseA()
.then(promiseB)
.then(promiseC)
.then(promiseD)
.catch(function(err){
console.log(err);
});
复制代码