node使用promise替代回调函数(7)
现在知道 Q.all 会在任意一个 promise 进入 reject 状态后立即进入 reject 状态。如果我们需要等到所有的 promise 都发生状态后(有的 fulfil, 有的 reject),再转换 Q.all 的状态, 这时我们可以使用 Q.allSettled
var Q = require('q'),
fs = require('fs');
/**
*读取文件内容
*@private
*/
function printFileContent(fileName) {
// Todo: 这段代码不够简洁。可以使用Q.denodeify来简化
var defer = Q.defer();
fs.readFile(fileName, 'utf8', function (err, data) {
if (!err && data) {
console.log(data);
defer.resolve(fileName + ' success ');
} else {
defer.reject(fileName + ' fail ');
}
})
return defer.promise;
}
Q.allSettled([printFileContent('nosuchfile.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])
.then(function (results) {
results.forEach(
function (result) {
console.log(result.state);
}
);
});
结束 promise 链
通常,对于一个 promise 链,有两种结束的方式。第一种方式是返回最后一个 promise
如 return foo().then(bar);
第二种方式就是通过 done 来结束 promise 链
如 foo().then(bar).done()
为什么需要通过 done 来结束一个 promise 链呢? 如果在我们的链中有错误没有被处理,那么在一个正确结束的 promise 链中,这个没被处理的错误会通过异常抛出
var Q = require('q');
function getPromise(msg, timeout, opt) {
var defer = Q.defer();
setTimeout(function () {
console.log(msg);
if (opt)
defer.reject(msg);
else
defer.resolve(msg);
}, timeout);
return defer.promise;
}
/**
* 没有用 done() 结束的 promise 链
* 由于 getPromse('2',2000,'opt') 返回 rejected, getPromise('3',1000) 就没有执行
* 然后这个异常并没有任何提醒,是一个潜在的 bug
*/
getPromise('1', 3000)
.then(function () { return getPromise('2', 2000, 'opt') })
.then(function () { return getPromise('3', 1000) });
/**
* 用 done() 结束的 promise 链
* 有异常抛出
*/
getPromise('1', 3000)
.then(function () { return getPromise('2', 2000, 'opt') })
.then(function () { return getPromise('3', 1000) })
.done();
附录:一个 Promise 简单的应用(Node.js笔记(5)promise)
附:Promises/A+ 规范
promise 代表一个异步操作的最终结果。主要通过 promise 的 then 方法订阅其最终结果的处理回调函数,和订阅因某原因无法成功获取最终结果的处理回调函数。
更对详细见:Promises/A+
A 与 A+ 的不同点
- A+ 规范通过术语 thenable 来区分 promise 对象
- A+ 定义 onFulfilled/onRejectd 必须是作为函数来调用,而且调用过程必须是异步的
