求分析 Async, Promise, EventProxy 优劣,哪个更适合服务端用来减少回调(可维护性,效率)
发布于 6 年前 作者 imWildCat 9000 次浏览 最后一次编辑是 4 年前

请前辈试从可维护性,执行效率,开发效率等方面分析。

另外在node中,Async和Promise之间的效率差是否可以忽略?

5 回复

沒用過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
});

同樣的代碼用 (一個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 是一种规范化异步接口,方便异步接口封装、处理的东西,它已经成了标准,目前仍有许多实现版本,但终归会趋于稳定,成为标准做法(要不要加之一?)。

回到顶部