Node的機制導很多的任務執行是異步的,一般用回調處理任務的結果。多任務就會導致多層嵌套。
於是Promise就被用來處理這個事情。尤其是bluebird
的Promise實現功能豐富。
如果需要一大串的任務全部執行完成之後繼續後面的,那麼就用Promise.all
方法,如果要任務順序執行,並把每次的結果單獨處理就用Promise.reduce
方法。
這兩個方法組合起來就可以發揮更加大的威力:
/**
* # Pipeline Utility
*
* Based on pipeline.js from when.js:
* https://github.com/cujojs/when/blob/3.7.4/pipeline.js
*/
var Promise = require('bluebird');
function pipeline(tasks /* initial arguments */) {
var args = Array.prototype.slice.call(arguments, 1),
runTask = function (task, args) {
// Self-optimizing function to run first task with multiple
// args using apply, but subsequent tasks via direct invocation
runTask = function (task, arg) {
return task(arg);
};
return task.apply(null, args);
};
// Resolve any promises for the arguments passed in first
return Promise.all(args).then(function (args) {
// Iterate through the tasks passing args from one into the next
return Promise.reduce(tasks, function (arg, task) {
return runTask(task, arg);
}, args);
});
}
module.exports = pipeline;
首先使用Promise.all
把參數都轉化成一個個的Promise
然後,用Promise.reduce
挨個執行任務,並且把每一個任務的結果依次傳遞到下一個任務。
來看看怎麼用的。
function modelQuery(options) {
return dataProvider.Post.findPage(options);
}
// Push all of our tasks into a `tasks` array in the correct order
tasks = [
utils.validate(docName, {opts: permittedOptions}),
utils.handlePublicPermissions(docName, 'browse'),
utils.convertOptions(allowedIncludes),
modelQuery
];
// Pipeline calls each task passing the result of one to be the arguments for the next
return pipeline(tasks, options);
注意: tasks
數組的每一個成員都返回一個方法。所以tasks
是一個Function
數組。是一組“任務”。