请前辈试从可维护性,执行效率,开发效率等方面分析。
另外在node中,Async和Promise之间的效率差是否可以忽略?
沒用過event proxy… 以下說法只考慮async 和promise
個人推介用promise >> async #執行效率 沒有實測... 留其他朋友補充...
#可讀性方面 跟你要處理的課題有關
##例子1: 你有一串數據都要用同一個函數處理 async 用法跟underscore 感覺差不多
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
同樣的代碼用Q (一個promise library)寫
Q.allSettled([
Q.nfapply(FS.stat, ["file1"]),
Q.nfapply(FS.stat, ["file2"]),
]).then(function (results) {
console.log(results);
})
.done(); //End the chain and throw any unhandle errors
aync 在這情況比Q 易讀
##例子2: 你要處理一些同步的功能像讀database
async.waterfall([
function(callback){
db = connectDb();
callback(null, db);
},
function(arg1, callback){
// arg1 now equals 'db'
query = arg1.query('select * from user');
callback(null, query);
},
function(arg1, callback){
// arg1 now equals 'query'
// process arg1.....
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
Q 的寫法, 假設這次所有database 函數都會回傳Q promise
connectDb()
.then(function (db) {
return db.query('select * from user');
})
.then(function (query) {
return query.process();
})
.then(function (results) {
console.log(results);
return results;
})
.done();
Q 在這情況比較好 因為它很像傳統的同步函數寫法. 如果加上錯誤處理 Q的可讀性應該更好...
以上例子都是async, q 的一些粗淺的用法... 應該會有更短更漂亮的演繹
我想帶出的是 用Q能表達一個直觀的線性思維.
不過兩者沒有衝突 可以混合一起用...不過我能用Q都用Q解決問題的
#開發效率方面... 如果從未用過promise, async會好promise 一點點
因為現在大部份的library 都只支援callback
fs.stat(path, callback);
async 天生和它們的親和力強, 因為它就是用這個callback 幹活的…
用promise 的話 你要先自行轉換callback做promise
var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", function (error, text) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(text);
}
});
return deferred.promise;
當然Q 也提供了short cut
Q.nfapply(FS.readFile, ["foo.txt", "utf-8"])
.then(function (text) {
console.log(text);
});
兩段代碼都在做同樣的事: 把callback 轉為promise
以上就是我對這兩個library 的觀感,有錯請指出
很感谢您写了这么多,对一个新人来说太有帮助了。
Q不错 可以考虑使用Generator
当然是用 Promise 啦
因为 ES6 里提供了 Promise (最新版的 firefox 和 chrome 都有,node 应该很快也会有了吧?),目前也可以通过 npm 里的 es6-promise 来调用
Promise 还可以与 Generator 结合,用法参考 mozilla 的 task.js 和 TJ 大神的 co
例子一如果用 bluebird 配合 bluebird 提供的 .promisifyAll
功能来做的话,可以写成这样:
var fs = Primise.promisifyAll(require('fs'))
Promise.all(
['file1','file2','file3'].map(function(fname) {
return fs.statAsync(fname)
})
)
.then(function(results) {
// handle results
})
.catch(function(err) {
console.error(err.stack)
})
同样的,所有符合 function(err, result) {}
这种规范的接口,都可以用它的 .promisify
转化为 Promise 风格的接口,和 Q 提供的 Q.nfcall
或者 Q.nfapply
类似,但是方便很多。
例子二可以补充一点,用 bluebird 不需要加 .done
强制抛出异常,bluebird 默认会提供一个 exceptionHandler。
async 只是个方便处理回调的工具库,为各种异步场景提供相应的工具函数;而 Promise 是一种规范化异步接口,方便异步接口封装、处理的东西,它已经成了标准,目前仍有许多实现版本,但终归会趋于稳定,成为标准做法(要不要加之一?)。