nodejs对外宣称的最大优势就是所谓的异步io,利用异步io,可以并行执行互相没有依赖的网络、数据库等操作,在某些场景下,这种方式可以极大的提高站点的响应速度
但是异步io也带来了代码本身逻辑的复杂性,比如一个应用,需要访问三个http数据源,然后综合比较三个数据源的结果,来得出最终的返回结果
三个数据源的回调执行顺序是不定的,这就需要一个计数器,在回调次数等于3时,再执行最终的处理程序
这里,借助js的高阶函数,来实现这个逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | var _httpLib = require('./lib/http.js'); //简单的http辅助类,如:get(url, callback) //高阶函数 var pending = (function(callback){ var count = 0, //计数 returns = {}; return function(key){ count++; //注册一个回调 return function(data){ count--; //执行一个回调 //按照并行逻辑的key保存返回结果 returns[key] = data; // returns[key] = data.substr(0, 100); if(count === 0){ //所有回调都执行以后,运行最终的逻辑 callback(returns); } }; }; }); //。。。怎么来准确的称呼done哪? var done = pending(function(returns){ //最终的处理逻辑 console.log('all-------over'); console.log(returns); }); //三个并行数据源 _httpLib.get('http://www.baidu.com', done('baidu')); _httpLib.get('http://www.qq.com', done('qq')); _httpLib.get('http://www.jiangkl.com', done('jkl')); |
~~~呵呵,看到一坨return、function,如果你还没晕,那么,恭喜你。反正我盯着这段代码看了不下10分钟,然后又执行了几次才算大概弄明白的
整个的逻辑,有点类似aop的思想,即对多个并行逻辑的回调做一个拦截、记录,这样可以更好的让程序员将注意力集中到业务逻辑上
pending是一个公用的并行处理函数
done是通过pending得到的具体的业务执行function,其回调参数就是前面提到的并行逻辑“最终的处理程序”
done()执行时,会将pending闭包内的计数器加1,同时返回一个function,作为httpget的回调
done()()执行时,计时器减1,同时将httpget的返回值保存
计数器减到0,“最终的处理程序”开始执行
———–
参考:http://www.infoq.com/cn/articles/generator-and-asynchronous-programming