写了多年的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