寫了多年的js,遇到過最蛋疼的事情莫過於callback hell, 相信你們也感同身受。node
業界許多大大也爲此提出了不少不錯的解決方案,我所瞭解的主要有:git
我這人閒着沒事也愛折騰,我也本身造輪子,不爲別的只爲本身代碼寫的舒服流暢.github
傳送門:目前只支持 node.js 環境,之後有時間再增長瀏覽器支持npm
爲啥叫avQ: 全稱是avril.queue由於哥喜歡avril就用她名字命名,跟島國無關api
核心:avQ做爲一個異步流程控制框架包含兩大要素來實現異步流程控制而且編碼方便流暢瀏覽器
var q = avQ();
var $fileContent = q.$await(fs.readFile, 'the/path/of/file.txt', function(err, res){ /*此時的this 並非指向q,而是一個新的avQ()對象 因此this實際上就是一個subQueue, this.error()會將error層層上拋默認只上拋不作任何處理,之後章節我會詳細介紹q.func執行的原理*/ this.error(err); return res; });
若是fs.readFile 須要上下文怎麼辦框架
q.$await, q.$each, 以及後面的q.$$await,q.$$each 都支持傳入context做爲第一個參數,例如異步
var $fileContent = q.$await(fs, fs.readFile, 'the/path/of/file.txt', function(err, res){ this.error(err); return res; }); var $$fileContent = q.$$await(fs, fs.readFile, 'the/path/of/file.txt'); // 會自動將 res 最爲 $awaitData 的結果 var $fileExisted = q.$await(fs.exists, 'the/path/of/file.txt'); // 默認將返回fs.existe 的 callback(existed) 中第一個參existed 數做爲值
var avQ = require('avril.queue'); var q = avQ();
/* return $AwaitData object */ var $fileContent = q.$await(fs.readFile, 'the/path/of/file.txt' , function(err, fileContent){ this.error(err); return fileContent; }); /* convert the $awaitData' result , return a new $AwaitData object */ var $ids = $fileContent.convert(function($org){ return $org.result().split('\n'); }); /* return $AwaitData object which result is list of */ var $users = q.$each(db.User.findById, $ids, function(err, user){ this.error(err); return user; }); q.func(function(){ console.log( $fileContent.result() ) console.log( $users.realResult() ); });
對於標準的node.js異步調用通常返回值是callback(err, result),ui
var $fileContent = q.$$await(fs.readFile, 'the/path/of/file.txt'); // 跟$await() 的區別在於$await 最後一個參數須要callback: return res;
$fileContent在異步請求完畢以後將會自動使用result 做爲結果.this
var avQ = require('avril.queue'); var q = avQ(); var $fileContent, $ids, $users; /* return $AwaitData object */ var filePath1 = 'the/path/of/file1.txt'; var filePath2 = 'the/path/of/file2.txt'; var $fileExisted = q.$await(fs.exists, filePath1); q.$if($fileExisted, function(){ $fileContent = this.$$await(fs.readFile, filePath1); }).$else(function(){ $fileContent = this.$$await(fs.readFile, filePath2); }); q.func(function(){ /* convert the $awaitData' result , return a new $AwaitData object */ $ids = $fileContent.convert(function($org){ return $org.result().split('\n'); }); /* return $AwaitData object which result is list of */ $users = this.$$each(db.User.findById, $ids); }); q.func(function(){ console.log( $fileContent.result() ) //只取出第一級 result() console.log( $users.realResult() ); // 遞歸取出全部的result() });
人無完人,碼無完碼,歡迎你們拍磚,若是你們有興趣我會繼續推出更多api文檔及介紹(你們沒興趣仍是要繼續寫完整,哈哈).
你們要以爲我這個庫有意思不妨給個github start