diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5199f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +.idea \ No newline at end of file diff --git a/README.md b/README.md index e7b4fdf..4f3c74d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,53 @@ async_demo ========== -A demo for async \ No newline at end of file +A demo for async. + ++ http://blog.fens.me/nodejs-async/ ++ http://blog.fens.me/nodejs-async-timer/ + +INSTALL +=========================== + +```{bash} +git clone https://github.com/bsspirit/async_demo.git +cd async_demo +``` + +Change Log +=================================== + +参考async@0.2.9版本的规范 + +https://github.com/caolan/async + +1. forEach.js改名为each.js +2. each.js文件中的async.forEach,改为async.each +3. map.js增加mapLimit函数 +4. filter_reject.js对注释补充 +5. filter_reject.js增加rejectSeries函数 +6. reduce.js增加注释 +7. detect.js增加注释 +8. sortBy.js增加注释 +9. some.js对注释补充 +10. every.js对注释补充和修改 +11. series.js调整注释格式 +12. parallel.js调整注释格式 +13. parallel.js增加parallelLimit函数 +14. whilist_until.js调整注释格式 +15. whilist_until.js增加doWhilst函数 +16. whilist_until.js增加doUntil函数 +17. whilist_until.js增加forever函数 +18. waterfall.js调整注释格式 +19. 增加compose.js文件 +20. apply.js补充注释并增加一个实例 +21. 修改nextTick.js实例 +22. 增加times.js文件,包括times和timesSeries函数 +23. 修改iterator.js实例 +24. 修正auto.js关于第二个实例的错误解释 +25. 修改queue.js实例和注释 +26. 修改cargo.js文件 +27. 增加applyEach.js文件 +28. 修改utils.js实例和注释 + + diff --git a/apply.js b/apply.js index a9663fc..cca5650 100644 --- a/apply.js +++ b/apply.js @@ -4,7 +4,7 @@ var t = require('./t'); var log = t.log; /** - * async.apply是一个非常好用的函数,可以让我们给一个函数预绑定多个参数并生成一个可直接调用的新函数,简化代码。 + * apply是一个非常好用的函数,可以让我们给一个函数预绑定多个参数并生成一个可直接调用的新函数,简化代码。 * * function(callback) { t.inc(3, callback); } * 等价于: @@ -12,16 +12,33 @@ var log = t.log; */ // apply(function, arguments..) +/** + * 通过名字绑定函数t.inc, t.fire,作为新函数给parallel调用 + */ +//1.1 async.parallel([ async.apply(t.inc, 3), async.apply(t.fire, 100) ], function (err, results) { - log('err: ', err); - log('results: ', results); + log('1.1 err: ', err); + log('1.1 results: ', results); }); +//58.605> 1.1 err: null +//58.613> 1.1 results: [ 4, 100 ] -// 预设参数 -var x = async.apply(t.inc, 1); -x(function(err, n){ - console.log('1.inc: ' + n); +/** + * 构造一个加法函数,通过apply简化代码 + */ +//1.2 +function inc(a,b,callback,timeout){ + var timeout = timeout || 200; + t.wait(200); + setTimeout(function() { + callback(null, a+b); + }, timeout); +} +var fn = async.apply(inc, 1, 2); +fn(function(err, n){ + log('1.2 inc: ' + n); }); +//58.616> 1.2 inc: 3 \ No newline at end of file diff --git a/applyEach.js b/applyEach.js new file mode 100644 index 0000000..19c4654 --- /dev/null +++ b/applyEach.js @@ -0,0 +1,79 @@ +var async = require('async'); +var t = require('./t'); +var log = t.log; + +/** +* applyEach,可以实现给一数组中每个函数传相同参数,通过callback返回。 +* 如果只传第一个参数,将返回一个函数对象,我可以传参调用。 +*/ +// applyEach(fns, args..., callback) + +/** + * 异步执行,给数组中的函数,他们有相同的参数。 + */ +//1.1 +async.applyEach([ + function (name,cb) { + setTimeout(function () { + log("1.1 handler: " + name + " A"); + cb(null, name); + }, 500); + }, function (name,cb) { + setTimeout(function () { + log("1.1 handler: " + name + " B"); + cb(null, name); + }, 150); + } +], 'Hello', function (err) { + log('1.1 err: ', err); +}); +//06.739> 1.1 handler: Hello B +//07.079> 1.1 handler: Hello A +//07.080> 1.1 err: null + +/** + * 异步执行,当只设置第一参数后,得到函数对象,再传参调用这个函数。 + */ +//1.2 +var fn = async.applyEach([ + function (name,cb) { + setTimeout(function () { + log("1.2 handler: " + name + " A"); + }, 500); + }, function (name,cb) { + setTimeout(function () { + log("1.2 handler: " + name + " B"); + }, 150); + } +]); +fn("simgle",function(err){ + log('err: ',err); +}); +//29.351> 1.2 handler: simgle B +//29.688> 1.2 handler: simgle A + +/** + * applyEachSeries与applyEach唯一不同的是,数组的函数同步执行。 + */ +//applyEachSeries(arr, args..., callback) +//1.3 +async.applyEachSeries([ + function (name,cb) { + setTimeout(function () { + log("1.3 handler: " + name + " A"); + cb(null, name); + }, 500); + }, function (name,cb) { + setTimeout(function () { + log("1.3 handler: " + name + " B"); + cb(null, name); + }, 150); + } +], "aaa", function (err) { + log('1.3 err: ', err); +}); +//10.669> 1.3 handler: aaa A +//10.831> 1.3 handler: aaa B +//10.834> 1.3 err: null + + diff --git a/auto.js b/auto.js index c5054c7..7a2c6d4 100644 --- a/auto.js +++ b/auto.js @@ -1,17 +1,15 @@ var async = require('async'); - var t = require('./t'); var log = t.log; /** - * async.auto用来处理有依赖关系的多个任务的执行。比如某些任务之间彼此独立,可以并行执行;但某些任务依赖于其它某些任务,只能等那些任务完成后才能执行。 - * - * 虽然我们可以使用async.parallel和async.series结合起来实现该功能,但如果任务之间关系复杂,则代码会相当复杂,以后如果想添加一个新任务,也会很麻烦。 + * auto用来处理有依赖关系的多个任务的执行。 * - * 这时使用async.auto,则会事半功倍。 + * 比如某些任务之间彼此独立,可以并行执行;但某些任务依赖于其它某些任务,只能等那些任务完成后才能执行。 + * 虽然我们可以使用parallel和series结合起来实现该功能,但如果任务之间关系复杂,则代码会相当复杂,以后如果想添加一个新任务,也会很麻烦。 + * 这时使用auto,则会事半功倍。 * * 如果有任务中途出错,则会把该错误传给最终callback,所有任务(包括已经执行完的)产生的数据将被忽略。 - * * 如果不关心错误和最终数据,可以不用写最后那个callback。 */ // async.auto(tasks, [callback]) @@ -24,7 +22,6 @@ var log = t.log; * 4. 发送邮件,将文件以附件形式发送给其它人。 * * 分析该任务,可以知道1与2可以并行执行,3需要等1和2完成,4要等3完成。 - * * 可以按以下方式来使用auto函数。 */ // 1.1 @@ -32,13 +29,13 @@ async.auto({ getData: function (callback) { setTimeout(function(){ console.log('1.1: got data'); - callback(); + callback(null, 'mydata'); }, 300); }, makeFolder: function (callback) { setTimeout(function(){ console.log('1.1: made folder'); - callback(); + callback(null, 'myfolder'); }, 200); }, writeFile: ['getData', 'makeFolder', function(callback) { @@ -48,20 +45,28 @@ async.auto({ }, 300); }], emailFiles: ['writeFile', function(callback, results) { - log('1.1: emailed file: ', results.writeFile); // -> myfile + log('1.1: emailed file: ', results.writeFile); callback(null, results.writeFile); }] }, function(err, results) { - log('1.1: err: ', err); // -> null - log('1.1: results: ', results); // -> { makeFolder: undefined, - // getData: undefined, - // writeFile: 'myfile', - // emailFiles: 'myfile' } + log('1.1: err: ', err); + log('1.1: results: ', results); }); +//1.1: made folder +//1.1: got data +//1.1: wrote file +//20.120> 1.1: emailed file: myfile +//20.125> 1.1: err: null +//20.127> 1.1: results: { makeFolder: 'myfolder', +// getData: 'mydata', +// writeFile: 'myfile', +// emailFiles: 'myfile' } + + /** - * 如果中途出错,则会把错误交给最终callback,所有任务(包括执行完的和未执行完的)产生的数据都被忽略。 - */ +* 如果中途出错,则会把错误交给最终callback,执行完任务的传给最终callback。未执行完成的函数值被忽略 +*/ // 1.2 async.auto({ getData: function (callback) { @@ -76,17 +81,24 @@ async.auto({ callback(null, 'myfolder'); }, 200); }, - writeFile: ['getData', 'makeFolder', function(callback, results) { + writeFile: ['getData', 'makeFolder', function(results, callback) { setTimeout(function(){ console.log('1.2: wrote file'); callback('myerr'); }, 300); }], - emailFiles: ['writeFile', function(callback, results) { + emailFiles: ['writeFile', function(results, callback) { console.log('1.2: emailed file: ' + results.writeFile); callback('err sending email', results.writeFile); }] }, function(err, results) { - log('1.2 err: ', err); // -> myerr - log('1.2 results: ', results); // -> '' -}); \ No newline at end of file + log('1.2 err: ', err); + log('1.2 results: ', results); +}); +//1.2: made folder +//1.2: got data +//1.2: wrote file +//51.399> 1.2 err: myerr +//51.401> 1.2 results: { makeFolder: 'myfolder', +// getData: 'mydata', +// writeFile: undefined } diff --git a/cargo.js b/cargo.js new file mode 100644 index 0000000..b0ccf1a --- /dev/null +++ b/cargo.js @@ -0,0 +1,86 @@ +var async = require('async'); +var t = require('./t'); +var log = t.log; + +/** + * cargo也是一个串行的消息队列,类似于queue,通过限制了worker数量,不再一次性全部执行。 + * 当worker数量不够用时,新加入的任务将会排队等候,直到有新的worker可用。 + * + * cargo的不同之处在于,cargo每次会加载满额的任务做为任务单元,只有任务单元中全部执行完成后,才会加载新的任务单元。 + */ +// cargo(worker, [payload]) + +/** + * 创建cargo实例 + */ +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i all workers to be used +//40.020> no more tasks wating +//40.020> start A +//40.020> start B +//40.322> finished processing A +//40.923> finished processing B +//40.923> no more tasks wating +//40.924> start C +//40.924> start D +//41.425> finished processing C +//41.526> finished processing D +//41.526> no more tasks wating +//41.527> start E +//41.728> finished processing E +//41.728> all tasks have been processed +//41.729> all tasks have been processed +//41.729> all tasks have been processed +//41.729> all tasks have been processed +//41.730> all tasks have been processed \ No newline at end of file diff --git a/compose.js b/compose.js new file mode 100644 index 0000000..ead9503 --- /dev/null +++ b/compose.js @@ -0,0 +1,42 @@ +var async = require('async'); +var t = require('./t'); +var log = t.log; + +/** + * 创建一个包括一组异步函数的函数集合,每个函数会消费上一次函数的返回值。 + * 把f(),g(),h()异步函数,组合成f(g(h()))的形式,通过callback得到返回值。 + */ +// compose(fn1, fn2...) + +/** + * 通过compose组合,f(g(h()))的形式,从内层到外层的执行的顺序。 + */ +//1.1 +function f(n,callback){ + log('1.1.f enter: ',n); + setTimeout(function () { + callback(null, n + 1); + }, 10); +} +function g(n, callback) { + log('1.1.g enter: ',n); + setTimeout(function () { + callback(null, n * 2); + }, 10); +} +function h(n, callback) { + log('1.1.h enter: ',n); + setTimeout(function () { + callback(null, n - 10); + }, 10); +} +var fgh = async.compose(f,g,h); +fgh(4,function(err,result){ + log('1.1 err: ', err); + log('1.1 result: ', result); +}); +//05.307> 1.1.h enter: 4 +//05.329> 1.1.g enter: -6 +//05.341> 1.1.f enter: -12 +//05.361> 1.1 err: null +//05.362> 1.1 result: -11 \ No newline at end of file diff --git a/concat.js b/concat.js index cfa9a5e..7bf19d9 100644 --- a/concat.js +++ b/concat.js @@ -4,7 +4,7 @@ var t = require('./t'); var log = t.log; /** - * 将合并多个异步操作的结果合并为一个数组。 + * 将多个异步操作的结果合并为一个数组。 */ // concat(arr, iterator(item,callback(err,result)), callback(err,result)) diff --git a/detect.js b/detect.js index ba74518..508a59d 100644 --- a/detect.js +++ b/detect.js @@ -3,14 +3,21 @@ var async = require('async'); var t = require('./t'); var log = t.log; -/** - * ����ȡ�ü��������������ĵ�һ��Ԫ�ء�����Ϊ������˳��ִ�����ַ�ʽ���ֱ��Ӧ����detect��detectSeries�� +/** + * 用于取得集合中满足条件的第一个元素。 + * 它分为并行与顺序执行两种方式,分别对应函数detect和detectSeries。 */ - // detect(array, iterator(item,callback(test)), callback(result) -var arr = [{value:1,delay:500}, - {value:2,delay:200}, - {value:3,delay:300}]; + +var arr = [ + {value:1,delay:500}, + {value:2,delay:200}, + {value:3,delay:300} +]; + +/** + * 并行执行,通过t.inc做一个累加器,得到第一个满足条件的结果对象 + */ async.detect(arr, function(item,callback){ log('1.1 enter: ', item.value); t.inc(item.value, function(err,n) { @@ -29,6 +36,9 @@ async.detect(arr, function(item,callback){ // 10.438> 1.1 handle: 1 // 10.438> 1.1 handle: 1 +/** + * 串行执行,通过t.inc做一个累加器,得到第一个满足条件的结果对象 + */ async.detectSeries(arr, function(item,callback) { log('1.2 enter: ', item.value); t.inc(item.value, function(err,n) { @@ -39,4 +49,4 @@ async.detectSeries(arr, function(item,callback) { log('1.2 result: ', result); }); // 09.928> 1.2 enter: 1 -// 10.438> 1.2 result: { value: 1, delay: 500 } \ No newline at end of file +// 10.438> 1.2 result: { value: 1, delay: 500 } diff --git a/forEach.js b/each.js similarity index 85% rename from forEach.js rename to each.js index 324f338..9de19df 100644 --- a/forEach.js +++ b/each.js @@ -1,145 +1,145 @@ -var async = require('async'); - -var t = require('./t'); -var log = t.log; - -/** - * 如果想对同一个集合中的所有元素都执行同一个异步操作,可以利用forEach函数。 - * - * async提供了三种方式: - * 1. 集合中所有元素并行执行 - * 2. 一个一个顺序执行 - * 3. 分批执行,同一批内并行,批与批之间按顺序 - * - * 如果中途出错,则错误将上传给最终的callback处理。其它已经启动的任务继续执行,未启动的忽略。 - */ -// forEach(arr, iterator(item, callback), callback(err)) - - -var arr = [{name:'Jack', delay: 200}, - {name:'Mike', delay: 100}, - {name:'Freewind', delay: 300}]; - -/** - * 所有操作并发执行,且全部未出错,最终得到的err为undefined。注意最终callback只有一个参数err。 - */ -// 1.1 -async.forEach(arr, function(item, callback) { - log('1.1 enter: ' + item.name); - setTimeout(function(){ - log('1.1 handle: ' + item.name); - callback(null, item.name); - }, item.delay); -}, function(err) { - log('1.1 err: ' + err); -}); -// 输出如下: -// 42.244> 1.1 enter: Jack -// 42.245> 1.1 enter: Mike -// 42.245> 1.1 enter: Freewind -// 42.350> 1.1 handle: Mike -// 42.445> 1.1 handle: Jack -// 42.554> 1.1 handle: Freewind -// 42.554> 1.1 err: undefined - - -/** - * 如果中途出错,则出错后马上调用最终的callback。其它未执行完的任务继续执行。 - */ -async.forEach(arr,function(item, callback) { - log('1.2 enter: ' +item.name); - setTimeout(function() { - log('1.2 handle: ' + item.name); - if(item.name==='Jack') { - callback('myerr'); - } - }, item.delay); -}, function(err) { - log('1.2 err: ' + err); -}); -// 输出如下: -// 42.246> 1.2 enter: Jack -// 42.246> 1.2 enter: Mike -// 42.246> 1.2 enter: Freewind -// 42.350> 1.2 handle: Mike -// 42.445> 1.2 handle: Jack -// 42.446> 1.2 err: myerr -// 42.555> 1.2 handle: Freewind - -/** - * 与forEach相似,但不是并行执行。而是一个个按顺序执行。 - */ -async.forEachSeries(arr, function(item, callback) { - log('1.3 enter: ' + item.name); - setTimeout(function(){ - log('1.3 handle: ' + item.name); - callback(null, item.name); - }, item.delay); -}, function(err) { - log('1.3 err: ' + err); -}); -// 42.247> 1.3 enter: Jack -// 42.459> 1.3 handle: Jack -// 42.459> 1.3 enter: Mike -// 42.569> 1.3 handle: Mike -// 42.569> 1.3 enter: Freewind -// 42.883> 1.3 handle: Freewind -// 42.883> 1.3 err: undefined - -/** - * 如果中途出错,则马上把错误传给最终的callback,还未执行的不再执行。 - */ -async.forEachSeries(arr,function(item, callback) { - log('1.4 enter: ' +item.name); - setTimeout(function() { - log('1.4 handle: ' + item.name); - if(item.name==='Jack') { - callback('myerr'); - } - }, item.delay); -}, function(err) { - log('1.4 err: ' + err); -}); -// 42.247> 1.4 enter: Jack -// 42.460> 1.4 handle: Jack -// 42.460> 1.4 err: myerr - -/** - * 分批执行,第二个参数是每一批的个数。每一批内并行执行,但批与批之间按顺序执行。 - */ -async.forEachLimit(arr, 2, function(item, callback) { - log('1.5 enter: ' + item.name); - setTimeout(function(){ - log('1.5 handle: ' + item.name); - callback(null, item.name); - }, item.delay); -}, function(err) { - log('1.5 err: ' + err); -}); -// 42.247> 1.5 enter: Jack -// 42.248> 1.5 enter: Mike -// 42.351> 1.5 handle: Mike -// 42.352> 1.5 enter: Freewind -// 42.461> 1.5 handle: Jack -// 42.664> 1.5 handle: Freewind -// 42.664> 1.5 err: undefined - -/** - * 如果中途出错,错误将马上传给最终的callback。同一批中的未执行完的任务还将继续执行,但下一批及以后的不再执行。 - */ -async.forEachLimit(arr,2,function(item, callback) { - log('1.6 enter: ' +item.name); - setTimeout(function() { - log('1.6 handle: ' + item.name); - if(item.name==='Jack') { - callback('myerr'); - } - }, item.delay); -}, function(err) { - log('1.6 err: ' + err); -}); -// 42.248> 1.6 enter: Jack -// 42.248> 1.6 enter: Mike -// 42.352> 1.6 handle: Mike -// 42.462> 1.6 handle: Jack +var async = require('async'); + +var t = require('./t'); +var log = t.log; + +/** + * 如果想对同一个集合中的所有元素都执行同一个异步操作,可以利用each函数。 + * + * async提供了三种方式: + * 1. 集合中所有元素并行执行 + * 2. 一个一个顺序执行 + * 3. 分批执行,同一批内并行,批与批之间按顺序 + * + * 如果中途出错,则错误将上传给最终的callback处理。其它已经启动的任务继续执行,未启动的忽略。 + */ +// each(arr, iterator(item, callback), callback(err)) + + +var arr = [{name:'Jack', delay: 200}, + {name:'Mike', delay: 100}, + {name:'Freewind', delay: 300}]; + +/** + * 所有操作并发执行,且全部未出错,最终得到的err为undefined。注意最终callback只有一个参数err。 + */ +// 1.1 +async.each(arr, function(item, callback) { + log('1.1 enter: ' + item.name); + setTimeout(function(){ + log('1.1 handle: ' + item.name); + callback(null, item.name); + }, item.delay); +}, function(err) { + log('1.1 err: ' + err); +}); +// 输出如下: +// 42.244> 1.1 enter: Jack +// 42.245> 1.1 enter: Mike +// 42.245> 1.1 enter: Freewind +// 42.350> 1.1 handle: Mike +// 42.445> 1.1 handle: Jack +// 42.554> 1.1 handle: Freewind +// 42.554> 1.1 err: undefined + + +/** + * 如果中途出错,则出错后马上调用最终的callback。其它未执行完的任务继续执行。 + */ +async.each(arr,function(item, callback) { + log('1.2 enter: ' +item.name); + setTimeout(function() { + log('1.2 handle: ' + item.name); + if(item.name==='Jack') { + callback('myerr'); + } + }, item.delay); +}, function(err) { + log('1.2 err: ' + err); +}); +// 输出如下: +// 42.246> 1.2 enter: Jack +// 42.246> 1.2 enter: Mike +// 42.246> 1.2 enter: Freewind +// 42.350> 1.2 handle: Mike +// 42.445> 1.2 handle: Jack +// 42.446> 1.2 err: myerr +// 42.555> 1.2 handle: Freewind + +/** + * 与each相似,但不是并行执行。而是一个个按顺序执行。 + */ +async.eachSeries(arr, function(item, callback) { + log('1.3 enter: ' + item.name); + setTimeout(function(){ + log('1.3 handle: ' + item.name); + callback(null, item.name); + }, item.delay); +}, function(err) { + log('1.3 err: ' + err); +}); +// 42.247> 1.3 enter: Jack +// 42.459> 1.3 handle: Jack +// 42.459> 1.3 enter: Mike +// 42.569> 1.3 handle: Mike +// 42.569> 1.3 enter: Freewind +// 42.883> 1.3 handle: Freewind +// 42.883> 1.3 err: undefined + +/** + * 如果中途出错,则马上把错误传给最终的callback,还未执行的不再执行。 + */ +async.eachSeries(arr,function(item, callback) { + log('1.4 enter: ' +item.name); + setTimeout(function() { + log('1.4 handle: ' + item.name); + if(item.name==='Jack') { + callback('myerr'); + } + }, item.delay); +}, function(err) { + log('1.4 err: ' + err); +}); +// 42.247> 1.4 enter: Jack +// 42.460> 1.4 handle: Jack +// 42.460> 1.4 err: myerr + +/** + * 分批执行,第二个参数是每一批的个数。每一批内并行执行,但批与批之间按顺序执行。 + */ +async.eachLimit(arr, 2, function(item, callback) { + log('1.5 enter: ' + item.name); + setTimeout(function(){ + log('1.5 handle: ' + item.name); + callback(null, item.name); + }, item.delay); +}, function(err) { + log('1.5 err: ' + err); +}); +// 42.247> 1.5 enter: Jack +// 42.248> 1.5 enter: Mike +// 42.351> 1.5 handle: Mike +// 42.352> 1.5 enter: Freewind +// 42.461> 1.5 handle: Jack +// 42.664> 1.5 handle: Freewind +// 42.664> 1.5 err: undefined + +/** + * 如果中途出错,错误将马上传给最终的callback。同一批中的未执行完的任务还将继续执行,但下一批及以后的不再执行。 + */ +async.eachLimit(arr,2,function(item, callback) { + log('1.6 enter: ' +item.name); + setTimeout(function() { + log('1.6 handle: ' + item.name); + if(item.name==='Jack') { + callback('myerr'); + } + }, item.delay); +}, function(err) { + log('1.6 err: ' + err); +}); +// 42.248> 1.6 enter: Jack +// 42.248> 1.6 enter: Mike +// 42.352> 1.6 handle: Mike +// 42.462> 1.6 handle: Jack // 42.462> 1.6 err: myerr \ No newline at end of file diff --git a/every.js b/every.js index f646208..c537af4 100644 --- a/every.js +++ b/every.js @@ -4,15 +4,15 @@ var t = require('./t'); var log = t.log; /** - * ���������ÿһ��Ԫ�ض������������򴫸����ջص���resultΪtrue������Ϊfalse + * 如果集合里每一个元素都满足条件,则传给最终回调的result为true,否则为false */ // every(arr, iterator(item,callback), callback(result)) -//alias: any +//alias: all var arr = [1,2,3,6]; /** - * ���������е�Ԫ�ض�<=10������Ϊtrue + * 并行执行,集合中所有的元素都<=10,所以为true */ async.every(arr, function(item,callback){ log('1.1 enter: ',item); @@ -34,7 +34,7 @@ async.every(arr, function(item,callback){ // 32.233> 1.1 result: true /** - * ������������һ��Ԫ�ز�����2������Ϊfalse + * 并行执行,集合中至少有一个元素不大于2,所以为false */ async.every(arr, function(item,callback){ log('1.2 enter: ',item); diff --git a/filter_reject.js b/filter_reject.js index 2e4b0af..cc40ab1 100644 --- a/filter_reject.js +++ b/filter_reject.js @@ -1,112 +1,140 @@ -var async = require('async'); - -var t = require('./t'); -var log = t.log; - -/** - * 使用异步操作对集合中的元素进行筛选。需要注意的是,iterator的callback只有一个参数,只能接收true或false。 - * - * 对于出错,该函数没有做出任何处理,直接由nodejs抛出。所以需要注意对Error的处理。 - * - * async提供了两种方式: - * 1. 并行执行:filter - * 2. 顺序执行:filterSereis - */ -// filter(arr, iterator(item, callback(test)), callback(results)) - -var arr = [1,2,3,4,5]; - -/** - * 并行执行,对arr进行筛选。 - */ -async.filter(arr, function(item, callback) { - log('1.1 enter: ' + item); - setTimeout(function() { - log('1.1 test: ' + item); - callback(item>=3); - }, 200); -}, function(results) { - log('1.1 results: ', results); -}); -// 16.739> 1.1 enter: 1 -// 16.749> 1.1 enter: 2 -// 16.749> 1.1 enter: 3 -// 16.749> 1.1 enter: 4 -// 16.749> 1.1 enter: 5 -// 16.749> 1.3 enter: 1 -// 16.949> 1.1 test: 1 -// 16.949> 1.1 test: 2 -// 16.949> 1.1 test: 3 -// 16.949> 1.1 test: 4 -// 16.949> 1.1 test: 5 -// 16.949> 1.1 results: [ 3, 4, 5 ] - - -/** - * 如果出错,将会由nodejs抛出,导致出错。为保证其它代码正常运行,注释掉该测试。 - */ -/* -async.filter(arr, function(item, callback) { - log('1.2 enter: ' + item); - setTimeout(function() { - log('1.2 handle: ' + item); - if(item===2) { - throw new Error('myerr'); - } - callback(item>=3); - }, 100); -}, function(results) { - log('1.2 results: ', results); -}); -*/ - -/** - * 并行执行,对arr进行筛选。 - */ -// 1.3 -async.filterSeries(arr, function(item, callback) { - log('1.3 enter: ' + item); - setTimeout(function() { - log('1.3 handle: ' + item); - callback(item>=3); - }, 200); -}, function(results) { - log('1.3 results: ', results); -}); -// 16.749> 1.3 enter: 1 -// 16.949> 1.3 handle: 1 -// 16.949> 1.3 enter: 2 -// 17.149> 1.3 handle: 2 -// 17.149> 1.3 enter: 3 -// 17.369> 1.3 handle: 3 -// 17.369> 1.3 enter: 4 -// 17.589> 1.3 handle: 4 -// 17.589> 1.3 enter: 5 -// 17.789> 1.3 handle: 5 -// 17.789> 1.3 results: [ 3, 4, 5 ] - - -/* - * reject跟filter正好相反,当测试为true时,抛弃之 - */ -// reject(arr, iterator(item, callback(test)), callback(results) -async.reject(arr, function(item, callback) { - log('1.4 enter: ' + item); - setTimeout(function() { - log('1.4 test: ' + item); - callback(item>=3); - }, 200); -}, function(results) { - log('1.4 results: ', results); -}); -// 31.359> 1.4 enter: 1 -// 31.359> 1.4 enter: 2 -// 31.359> 1.4 enter: 3 -// 31.359> 1.4 enter: 4 -// 31.359> 1.4 enter: 5 -// 31.559> 1.4 test: 1 -// 31.559> 1.4 test: 2 -// 31.559> 1.4 test: 3 -// 31.559> 1.4 test: 4 -// 31.559> 1.4 test: 5 -// 31.569> 1.4 results: [ 1, 2 ] \ No newline at end of file +var async = require('async'); + +var t = require('./t'); +var log = t.log; + +/** + * 使用异步操作对集合中的元素进行筛选。需要注意的是,iterator的callback只有一个参数,只能接收true或false。 + * + * 对于出错,该函数没有做出任何处理,直接由nodejs抛出。所以需要注意对Error的处理。 + * + * async提供了两种方式: + * 1. 并行执行:filter + * 2. 顺序执行:filterSereis + */ +// filter(arr, iterator(item, callback(test)), callback(results)) + +var arr = [1,2,3,4,5]; + +/** + * 并行执行,对arr进行筛选。 + */ +async.filter(arr, function(item, callback) { + log('1.1 enter: ' + item); + setTimeout(function() { + log('1.1 test: ' + item); + callback(item>=3); + }, 200); +}, function(results) { + log('1.1 results: ', results); +}); +//16.739> 1.1 enter: 1 +//16.749> 1.1 enter: 2 +//16.749> 1.1 enter: 3 +//16.749> 1.1 enter: 4 +//16.749> 1.1 enter: 5 +//16.749> 1.3 enter: 1 +//16.949> 1.1 test: 1 +//16.949> 1.1 test: 2 +//16.949> 1.1 test: 3 +//16.949> 1.1 test: 4 +//16.949> 1.1 test: 5 +//16.949> 1.1 results: [ 3, 4, 5 ] + + +/** +* 如果出错,将会由nodejs抛出,导致出错。为保证其它代码正常运行,注释掉该测试。 +* +* try..catch:抓不到这个错误 +*/ +/* +async.filter(arr, function(item, callback) { + log('1.2 enter: ' + item); + setTimeout(function() { + log('1.2 handle: ' + item); + if(item===2) { + throw new Error('myerr'); + } + callback(item>=3); + }, 100); +}, function(results) { + log('1.2 results: ', results); +}); +*/ + +/** +* 串行执行,对arr进行筛选。 +*/ +// 1.3 +async.filterSeries(arr, function(item, callback) { + log('1.3 enter: ' + item); + setTimeout(function() { + log('1.3 handle: ' + item); + callback(item>=3); + }, 200); +}, function(results) { + log('1.3 results: ', results); +}); +// 16.749> 1.3 enter: 1 +// 16.949> 1.3 handle: 1 +// 16.949> 1.3 enter: 2 +// 17.149> 1.3 handle: 2 +// 17.149> 1.3 enter: 3 +// 17.369> 1.3 handle: 3 +// 17.369> 1.3 enter: 4 +// 17.589> 1.3 handle: 4 +// 17.589> 1.3 enter: 5 +// 17.789> 1.3 handle: 5 +// 17.789> 1.3 results: [ 3, 4, 5 ] + + +/* +* reject跟filter正好相反,当测试为true时,抛弃之 +*/ +// reject(arr, iterator(item, callback(test)), callback(results) +async.reject(arr, function(item, callback) { + log('1.4 enter: ' + item); + setTimeout(function() { + log('1.4 test: ' + item); + callback(item>=3); + }, 200); +}, function(results) { + log('1.4 results: ', results); +}); +// 31.359> 1.4 enter: 1 +// 31.359> 1.4 enter: 2 +// 31.359> 1.4 enter: 3 +// 31.359> 1.4 enter: 4 +// 31.359> 1.4 enter: 5 +// 31.559> 1.4 test: 1 +// 31.559> 1.4 test: 2 +// 31.559> 1.4 test: 3 +// 31.559> 1.4 test: 4 +// 31.559> 1.4 test: 5 +// 31.569> 1.4 results: [ 1, 2 ] + + +/** + * 串行执行,对arr进行筛选。 + */ +// 1.3 +async.rejectSeries(arr, function(item, callback) { + log('1.5 enter: ' + item); + setTimeout(function() { + log('1.5 handle: ' + item); + callback(item>=3); + }, 200); +}, function(results) { + log('1.5 results: ', results); +}); +//43.592> 1.5 enter: 1 +//43.799> 1.5 handle: 1 +//43.800> 1.5 enter: 2 +//44.004> 1.5 handle: 2 +//44.007> 1.5 enter: 3 +//44.210> 1.5 handle: 3 +//44.211> 1.5 enter: 4 +//44.412> 1.5 handle: 4 +//44.413> 1.5 enter: 5 +//44.614> 1.5 handle: 5 +//44.616> 1.5 results: [ 1, 2 ] \ No newline at end of file diff --git a/iterator.js b/iterator.js index a55fc55..ae43a5d 100644 --- a/iterator.js +++ b/iterator.js @@ -1,36 +1,61 @@ var async = require('async'); - var t = require('./t'); var log = t.log; /** - * 将一组函数包装成为一个iterator,可通过next()得到以下一个函数为起点的新的iterator。该函数通常由async在内部使用,但如果需要时,也可在我们的代码中使用它。 + * 将一组函数包装成为一个iterator,初次调用此iterator时,会执行定义中的第一个函数并返回第二个函数以供调用。 + * 也可通过手动调用 next() 得到以下一个函数为起点的新的iterator。 + * 该函数通常由async在内部使用,但如果需要时,也可在我们的代码中使用它。 */ // async.iterator(tasks) var iter = async.iterator([ - function() { console.log('111') }, - function() { console.log('222') }, - function() { console.log('333') } + function () {log('I am 111')}, + function () {log('I am 222')}, + function () {log('I am 333')} ]); -// 直接调用(),会执行当前函数,并返回一个由下个函数为起点的新的iterator -console.log('------- iter() ---------'); -console.log(iter()); -console.log(iter()); +/** +* 直接调用(),会执行当前函数,并返回一个由下个函数为起点的新的iterator +*/ +//1.1 +log('1.1 iter()'); +var it1 = iter(); +it1(); +it1(); +//28.368> 1.1 iter() +//28.371> I am 111 +//28.372> I am 222 +//28.372> I am 222 -// 调用next(),不会执行当前函数,直接返回由下个函数为起点的新iterator -console.log('-------- iter.next() -------'); -console.log(iter.next()); -console.log(iter.next()); -console.log(iter.next()); -console.log(iter.next()); +/** +* 通过iter()来调用下一个函数 +*/ +log('1.2 iter()'); +var it2 = iter(); +var it3 = it2(); +var it4 = it3(); +//it4(); // 这句代码执行会报错 +log(it4); // => 'null' +//32.449> 1.2 iter() +//32.452> I am 111 +//32.452> I am 222 +//32.453> I am 333 +//32.454> null -// 对于同一个iterator,多次调用next(),不会影响自己 -console.log('-------- iter.next()() -------'); -console.log(iter.next()()); -console.log(iter.next()()); +/** + * 调用next(),不会执行当前函数,直接返回由下个函数为起点的新iterator + * 对于同一个iterator,多次调用next(),不会影响自己 + */ +//1.3 +log('1.3 iter()'); +var it5 = iter.next(); +it5(); +var it6 = iter.next().next(); +it6(); +iter(); +//39.895> 1.3 iter() +//39.898> I am 222 +//39.899> I am 333 +//39.899> I am 111 -// 如果只有一个元素,则next()返回null -console.log('--------- last.next() --------'); -console.log(iter.next().next().next()); \ No newline at end of file diff --git a/map.js b/map.js index 5573da9..9fb545c 100644 --- a/map.js +++ b/map.js @@ -4,7 +4,7 @@ var t = require('./t'); var log = t.log; /** - * 对集合中的每一个元素,执行某个异步操作,得到结果。所有的结果将汇总到最终的callback里。与forEach的区别是,forEach只关心操作不管最后的值,而map关心的最后产生的值。 + * 对集合中的每一个元素,执行某个异步操作,得到结果。所有的结果将汇总到最终的callback里。与each的区别是,each只关心操作不管最后的值,而map关心的最后产生的值。 * * 提供了两种方式: * 1. 并行执行。同时对集合中所有元素进行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的任务的结果,未执行完的占个空位 @@ -40,8 +40,8 @@ async.map(arr, function(item, callback) { // 54.879> 1.1 results: [ 'Jack!!!', 'Mike!!!', 'Freewind!!!', 'Test!!!' ] /** - * 如果中途出错,立刻将错误、以及已经执行完成的结果汇总给最终callback。未执行完的将会在结果数组中用占个空位。 - */ +* 如果中途出错,立刻将错误、以及已经执行完成的结果汇总给最终callback。未执行完的将会在结果数组中用占个空位。 +*/ async.map(arr, function(item, callback) { log('1.2 enter: ' + item.name); setTimeout(function() { @@ -65,8 +65,8 @@ async.map(arr, function(item, callback) { // 54.879> 1.2 handle: Freewind /** - * 顺序执行,一个完了才执行下一个。 - */ +* 顺序执行,一个完了才执行下一个。 +*/ async.mapSeries(arr, function(item, callback) { log('1.3 enter: ' + item.name); setTimeout(function() { @@ -89,8 +89,8 @@ async.mapSeries(arr, function(item, callback) { // 55.269> 1.3 results: [ 'Jack!!!', 'Mike!!!', 'Freewind!!!', 'Test!!!' ] /** - * 顺序执行过程中出错,只把错误以及执行完的传给最终callback,未执行的忽略。 - */ +* 顺序执行过程中出错,只把错误以及执行完的传给最终callback,未执行的忽略。 +*/ async.mapSeries(arr, function(item, callback) { log('1.4 enter: ' + item.name); setTimeout(function() { @@ -108,3 +108,29 @@ async.mapSeries(arr, function(item, callback) { // 47.931> 1.4 handle: Mike // 47.931> 1.4 err: myerr // 47.932> 1.4 results: [ 'Jack!!!', undefined ] + +/** + * 并行执行,同时最多2个函数并行,传给最终callback。 + */ +//1.5 +async.mapLimit(arr,2, function(item, callback) { + log('1.5 enter: ' + item.name); + setTimeout(function() { + log('1.5 handle: ' + item.name); + if(item.name==='Jack') callback('myerr'); + else callback(null, item.name+'!!!'); + }, item.delay); +}, function(err, results) { + log('1.5 err: ', err); + log('1.5 results: ', results); +}); +//57.797> 1.5 enter: Jack +//57.800> 1.5 enter: Mike +//57.900> 1.5 handle: Mike +//57.900> 1.5 enter: Freewind +//58.008> 1.5 handle: Jack +//58.009> 1.5 err: myerr +//58.009> 1.5 results: [ undefined, 'Mike!!!' ] +//58.208> 1.5 handle: Freewind +//58.208> 1.5 enter: Test +//58.273> 1.5 handle: Test diff --git a/nextTick.js b/nextTick.js index 2c7b6fd..b8bd8e2 100644 --- a/nextTick.js +++ b/nextTick.js @@ -1,20 +1,26 @@ var async = require('async'); +var t = require('./t'); +var log = t.log; /** - * async.nextTick的作用与nodejs的nextTick一样,都是把某个函数调用放在队列的尾部。但在浏览器端,只能使用setTimeout(callback,0),但这个方法有时候会让其它高优先级的任务插到前面去。 - * + * nextTick的作用与nodejs的nextTick一样,再最后调用函数。 + * 但在浏览器端,只能使用setTimeout(callback,0),但这个方法有时候会让其它高优先级的任务插到前面去。 * 所以提供了这个nextTick,让同样的代码在服务器端和浏览器端表现一致。 */ // nextTick(callback) var calls = []; - async.nextTick(function() { calls.push('two'); -});x - +}); +async.nextTick(function() { + log('1.1',calls); +}); calls.push('one'); - +log('1.2',calls); async.nextTick(function() { - console.log(calls); // -> [ 'one', 'two' ] -}); \ No newline at end of file + log('1.3',calls); +}); +//09.838> 1.2[ 'one' ] +//09.842> 1.1[ 'one', 'two' ] +//09.843> 1.3[ 'one', 'two' ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..f2f0b42 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "async_demo", + "version": "0.1.1", + "private": true, + "dependencies": { + "moment": "*", + "async": "*" + } +} diff --git a/parallel.js b/parallel.js index bd18df1..9c0c80a 100644 --- a/parallel.js +++ b/parallel.js @@ -1,17 +1,15 @@ var async = require('async'); +var t = require('./t'); +var log = t.log; /** * 并行执行多个函数,每个函数都是立即执行,不需要等待其它函数先执行。传给最终callback的数组中的数据按照tasks中声明的顺序,而不是执行完成的顺序。 * * 如果某个函数出错,则立刻将err和已经执行完的函数的结果值传给parallel最终的callback。其它未执行完的函数的值不会传到最终数据,但要占个位置。 - * * 同时支持json形式的tasks,其最终callback的结果也为json形式。 */ // parallel(tasks, [callback]) -var t = require('./t'); -var log = t.log; - /** * 并行执行多个函数,每个函数的值将按函数声明的先后顺序汇成一个数组,传给最终callback。 */ @@ -21,44 +19,77 @@ async.parallel([ function(cb) { t.fire('a200', cb, 200) }, function(cb) { t.fire('a300', cb, 300) } ], function (err, results) { - log('1.1 err: ', err); // -> undefined - log('1.1 results: ', results); // ->[ 'a400', 'a200', 'a300' ] + log('1.1 err: ', err); + log('1.1 results: ', results); }); +//36.929> 1.1 err: null +//36.930> 1.1 results: [ 'a400', 'a200', 'a300' ] /** - * 如果中途有个函数出错,则将该err和已经完成的函数值汇成一个数组,传给最终的callback。还没有执行完的函数的值将被忽略,但要在最终数组中占个位置 - */ +* 如果中途有个函数出错,则将该err和已经完成的函数值汇成一个数组,传给最终的callback。还没有执行完的函数的值将被忽略,但要在最终数组中占个位置 +*/ // 1.2 async.parallel([ function(cb) { log('1.2.1: ', 'start'); t.fire('a400', cb, 400) }, // 该函数的值不会传给最终callback,但要占个位置 function(cb) { log('1.2.2: ', 'start'); t.err('e200', cb, 200) }, function(cb) { log('1.2.3: ', 'start'); t.fire('a100', cb, 100) } ], function(err, results) { - log('1.2 err: ', err); // -> e200 - log('1.2 results: ', results); // -> [ , undefined, 'a100' ] + log('1.2 err: ', err); + log('1.2 results: ', results); }); +//36.537> 1.2.1: start +//36.540> 1.2.2: start +//36.541> 1.2.3: start +//36.741> 1.2 err: e200 +//36.744> 1.2 results: [ , undefined, 'a100' ] /** - * 以json形式传入tasks,最终results也为json - */ +* 以json形式传入tasks,最终results也为json +*/ // 1.3 async.parallel({ a: function(cb) { t.fire('a400', cb, 400) }, b: function(cb) { t.fire('c300', cb, 300) } }, function(err, results) { - log('1.3 err: ', err); // -> undefined - log('1.3 results: ', results); // -> { b: 'c300', a: 'a400' } + log('1.3 err: ', err); + log('1.3 results: ', results); }); +//36.943> 1.3 err: null +//36.944> 1.3 results: { b: 'c300', a: 'a400' } /** - * 如果中途出错,会将err与已经完成的函数值(汇成一个json)传给最终callback。未执行完成的函数值被忽略,不会出现在最终json中。 - */ +* 如果中途出错,会将err与已经完成的函数值(汇成一个json)传给最终callback。未执行完成的函数值被忽略,不会出现在最终json中。 +*/ // 1.4 async.parallel({ a: function(cb) { t.fire('a400', cb, 400) }, // 该函数的值不会传给最终的callback b: function(cb) { t.err('e300', cb, 300) }, c: function(cb) { t.fire('c200', cb, 200) } }, function(err, results) { - log('1.4 err: ', err); // -> e300 - log('1.4 results: ', results); // -> { c: 'c200', b: undefined } + log('1.4 err: ', err); + log('1.4 results: ', results); +}); +//36.853> 1.4 err: e300 +//36.854> 1.4 results: { c: 'c200', b: undefined } + +/** + * 并行执行,同时最多2个函数并行,传给最终callback。 + */ +//1.5 +async.parallelLimit({ + a:function(cb) { log('a start'); t.fire('a400', cb, 200) }, + b:function(cb) { log('b start'); t.fire('b200', cb, 200) }, + c:function(cb) { log('c start'); t.fire('c100', cb, 100) }, + d:function(cb) { log('d start'); t.fire('d600', cb, 600) }, + e:function(cb) { log('e start'); t.fire('e300', cb, 300) } +},2, function(err, results) { + log('1.5 err: ', err); + log('1.5 results: ', results); }); +//26.993> a start +//26.996> b start +//27.200> c start +//27.202> d start +//27.313> e start +//27.809> 1.5 err: +//27.810> 1.5 results: { a: 'a400', b: 'b200', c: 'c100', e: 'e300', d: 'd600' } \ No newline at end of file diff --git a/queue.js b/queue.js index b3ea7e4..6ee63d1 100644 --- a/queue.js +++ b/queue.js @@ -3,41 +3,51 @@ var t = require('./t'); var log = t.log; /** - * queue相当于一个加强版的parallel,主要是限制了worker数量,不再一次性全部执行。当worker数量不够用时,新加入的任务将会排队等候,直到有新的worker可用。 + * queue是一个串行的消息队列,通过限制了worker数量,不再一次性全部执行。 + * 当worker数量不够用时,新加入的任务将会排队等候,直到有新的worker可用。 * * 该函数有多个点可供回调,如worker用完时、无等候任务时、全部执行完时等。 */ // queue(worker, concurrency) -// 定义一个queue,设worker数量为2 +/** + * 定义一个queue,设worker数量为2 + */ var q = async.queue(function(task, callback) { log('worker is processing task: ', task.name); task.run(callback); }, 2); -// 如果某次push操作后,任务数将达到或超过worker数量时,将调用该函数 +/** + * 监听:如果某次push操作后,任务数将达到或超过worker数量时,将调用该函数 + */ q.saturated = function() { log('all workers to be used'); } -// 当最后一个任务交给worker时,将调用该函数 +/** + * 监听:当最后一个任务交给worker时,将调用该函数 + */ q.empty = function() { - log('no more tasks wating'); + log('no more tasks waiting'); } -// 当所有任务都执行完以后,将调用该函数 +/** + * 监听:当所有任务都执行完以后,将调用该函数 + */ q.drain = function() { - console.log('all tasks have been processed'); + log('all tasks have been processed'); } -// 放入单个任务 +/** +* 独立加入2个任务 +*/ q.push({name:'t1', run: function(cb){ log('t1 is running, waiting tasks: ', q.length()); t.fire('t1', cb, 400); // 400ms后执行 }}, function(err) { log('t1 executed'); }); - log('pushed t1, waiting tasks: ', q.length()); q.push({name:'t2',run: function(cb){ @@ -46,19 +56,61 @@ q.push({name:'t2',run: function(cb){ }}, function(err) { log('t2 executed'); }); - log('pushed t2, waiting tasks: ', q.length()); +//54.448> pushed t1, waiting tasks: 1 +//54.451> all workers to be used +//54.452> pushed t2, waiting tasks: 2 +//54.452> worker is processing task: t1 +//54.453> t1 is running, waiting tasks: 1 +//54.455> no more tasks wating +//54.455> worker is processing task: t2 +//54.455> t2 is running, waiting tasks: 0 +//54.656> t2 executed +//54.867> t1 executed +//54.868> all tasks have been processed -// 放入多个任务 -q.push([{name:'t3', run: function(cb){ - log('t3 is running, waiting tasks: ', q.length()); - t.fire('t3', cb, 300); // 300ms后执行 -}},{name:'t4', run: function(cb){ - log('t4 is running, waiting tasks: ', q.length()); - t.fire('t4', cb, 500); // 500ms后执行 -}}], function(err) { - log('t3/4 executed'); -}); -log('pushed t3/t4, waiting tasks: ', q.length()); +// 同时加入多个任务 +q.push([ + { + name:'t3', run: function(cb){ + log('t3 is running, waiting tasks: ', q.length()); + t.fire('t3', cb, 300); // 300ms后执行 + } + },{ + name:'t4', run: function(cb){ + log('t4 is running, waiting tasks: ', q.length()); + t.fire('t4', cb, 500); // 500ms后执行 + } + },{ + name:'t5', run: function(cb){ + log('t5 is running, waiting tasks: ', q.length()); + t.fire('t5', cb, 100); // 100ms后执行 + } + },{ + name:'t6', run: function(cb){ + log('t6 is running, waiting tasks: ', q.length()); + t.fire('t6', cb, 400); // 400ms后执行 + } + } +], function(err) { + log('err: ',err); +}); +log('pushed t3,t4,t5,t6 into queue, waiting tasks: ', q.length()); +//53.755> all workers to be used +//53.758> pushed t3,t4,t5,t6 into queue, waiting tasks: 4 +//53.759> worker is processing task: t3 +//53.760> t3 is running, waiting tasks: 3 +//53.762> worker is processing task: t4 +//53.762> t4 is running, waiting tasks: 2 +//54.073> err: null +//54.074> worker is processing task: t5 +//54.076> t5 is running, waiting tasks: 1 +//54.183> err: null +//54.184> no more tasks wating +//54.185> worker is processing task: t6 +//54.186> t6 is running, waiting tasks: 0 +//54.265> err: null +//54.588> err: null +//54.589> all tasks have been processed diff --git a/reduce.js b/reduce.js index 6b5e72a..879b300 100644 --- a/reduce.js +++ b/reduce.js @@ -4,13 +4,16 @@ var t = require('./t'); var log = t.log; /** - * Reduce���������Ǹ���һ����ʼֵ�������뼯���е�ÿһ��Ԫ�������㣬���õ�һ��ֵ��reduce��������������Ԫ�أ������������󣬿�ʹ��reduceRight�� + * Reduce可以让我们给定一个初始值,用它与集合中的每一个元素做运算,最后得到一个值。reduce从左向右来遍历元素,如果想从右向左,可使用reduceRight。 */ //reduce(arr, memo, iterator(memo,item,callback), callback(err,result)) //alias: inject, foldl var arr = [1,3,5]; +/** + * 顺序执行 + */ async.reduce(arr, 100, function(memo, item, callback) { log('1.1 enter: ' + memo +', ' + item); setTimeout(function() { @@ -26,6 +29,9 @@ async.reduce(arr, 100, function(memo, item, callback) { // 29.109> 1.1 err: // 29.109> 1.1 result: 109 +/** + * 顺序执行过程中出错,只把错误传给最终callback,结果是null + */ async.reduce(arr, 100, function(memo, item, callback) { log('1.2 enter: ' + memo +', ' + item); setTimeout(function() { @@ -41,7 +47,11 @@ async.reduce(arr, 100, function(memo, item, callback) { // 05.760> 1.2 err: myerr // 05.760> 1.2 result: -//alias: foldr +/** + * 顺序执行从右向左 + * + * alias: foldr + */ async.reduceRight(arr, 100, function(memo, item, callback) { log('1.3 enter: ' + memo +', ' + item); setTimeout(function() { @@ -57,7 +67,9 @@ async.reduceRight(arr, 100, function(memo, item, callback) { // 29.109> 1.3 err: // 29.109> 1.3 result: 109 -// +/** + * 通过t.inc做一个累加器,参与reduce的计算 + */ async.reduce(arr, 100, function(memo,item,callback) { log('1.4 enter: '+memo+','+item); t.inc(item, function(err,n) { @@ -78,6 +90,9 @@ async.reduce(arr, 100, function(memo,item,callback) { // 29.409> 1.4 result: 112 // --> spent 0.62s +/** + * 通过t.inc做一个累加器,并实现对map的结果集做reduce + */ async.map(arr, function(item, callback) { log('1.5 enter: ', item); t.inc(item, function(err,n){ diff --git a/series.js b/series.js index 430021f..5718f85 100644 --- a/series.js +++ b/series.js @@ -1,19 +1,16 @@ var async = require('async'); +var t = require('./t'); +var log = t.log; + /** - * series(tasks, [callback]) - * - * 依次执行一个函数数组中的每个函数,每一个函数执行完成之后才能执行下一个函数。 - * - * 如果任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,并且将会立刻会将该error以及已经执行了的函数的结果,传给series中最后那个callback。 + * 串行执行,一个函数数组中的每个函数,每一个函数执行完成之后才能执行下一个函数。 * + * 如果任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,并且会立刻将该error以及已经执行了的函数的结果,传给series中最后那个callback。 * 当所有的函数执行完后(没有出错),则会把每个函数传给其回调函数的结果合并为一个数组,传给series最后的那个callback。 - * * 还可以json的形式来提供tasks。每一个属性都会被当作函数来执行,并且结果也会以json形式传给series最后的那个callback。这种方式可读性更高一些。 */ - -var t = require('./t'); -var log = t.log; +// series(tasks, [callback]) /** * 全部函数都正常执行。每个函数产生的值将按顺序合并为一个数组,传给最终的callback。 @@ -24,9 +21,11 @@ async.series([ function(cb) { t.inc(8, cb); }, function(cb) { t.inc(2, cb); } ], function(err, results) { - log('1.1 err: ', err); // -> undefined - log('1.1 results: ', results); // -> [ 4, 9, 3 ] + log('1.1 err: ', err); + log('1.1 results: ', results); }); +//05.155> 1.1 err: null +//05.156> 1.1 results: [ 4, 9, 3 ] /** * 中间有函数出错。出错之后的函数不会执行,错误及之前正常执行的函数结果将传给最终的callback。 @@ -37,9 +36,11 @@ async.series([ function(cb) { t.err('test_err', cb); }, function(cb) { t.inc(8, cb); } ], function (err, results) { - log('1.2 err: ', err); // -> test_err - log('1.2 results: ', results); // -> [ 4, undefined ] + log('1.2 err: ', err); + log('1.2 results: ', results); }); +//04.964> 1.2 err: test_err +//04.973> 1.2 results: [ 4, undefined ] /** * 如果某个函数传的数据是undefined, null, {}, []等,它们会原样传给最终callback。 @@ -53,9 +54,11 @@ async.series([ function(cb) { t.fire([], cb); }, function(cb) { t.fire('abc', cb) } ], function(err, results) { - log('1.3 err: ', err); // -> undefined - log('1.3 results: ', results); // -> [ 3, undefined, null, {}, [], 'abc' ] + log('1.3 err: ', err); + log('1.3 results: ', results); }); +//05.794> 1.3 err: null +//05.795> 1.3 results: [ 3, undefined, null, {}, [], 'abc' ] /** * 以json形式传入tasks。其结果也将以json形式传给最终callback。 @@ -66,6 +69,8 @@ async.series({ c: function (cb) { t.err('myerr', cb); }, d: function (cb) { t.inc(8, cb); } }, function (err, results) { - log('1.4 err: ', err); // -> myerr - log('1.4 results: ', results); // -> { a: 4, b: undefined, c: undefined } -}); \ No newline at end of file + log('1.4 err: ', err); + log('1.4 results: ', results); +}); +//05.178> 1.4 err: myerr +//05.179> 1.4 results: { a: 4, b: undefined, c: undefined } \ No newline at end of file diff --git a/some.js b/some.js index 103485d..a9a16ed 100644 --- a/some.js +++ b/some.js @@ -4,7 +4,7 @@ var t = require('./t'); var log = t.log; /** - * ���������Ƿ�������һ��Ԫ����������ʱ������callback�õ���ֵΪtrue������Ϊfalse. + * 当集合中是否有至少一个元素满足条件时,最终callback得到的值为true,否则为false. */ // some(arr, iterator(item,callback(test)), callback(result)) //alias: any @@ -12,7 +12,7 @@ var log = t.log; var arr = [1,2,3,6]; /** - * ������������һ��Ԫ��<=3�����Խ��Ϊtrue + * 并行执行,集合中至少有一个元素<=3,所以结果为true */ // 1.1 async.some(arr, function(item,callback){ @@ -20,7 +20,7 @@ async.some(arr, function(item,callback){ setTimeout(function(){ log('1.1 handle: ',item); callback(item<=3); - },100); + },100); }, function(result) { log('1.1 result: ', result); }); @@ -36,7 +36,7 @@ async.some(arr, function(item,callback){ /** - * ������û��һ��Ԫ��>10�����Խ��Ϊfalse + * 串行执行,集合中没有一个元素>10,所以结果为false */ async.some(arr, function(item,callback){ log('1.2 enter: ',item); diff --git a/sortBy.js b/sortBy.js index ca44ed1..54ec433 100644 --- a/sortBy.js +++ b/sortBy.js @@ -4,12 +4,15 @@ var t = require('./t'); var log = t.log; /** - * �Լ����ڵ�Ԫ�ؽ�����������ÿ��Ԫ�ؽ���ij�첽�����������ֵ����С�������� + * 对集合内的元素进行排序,依据每个元素进行某异步操作后产生的值,从小到大排序。 */ // sortBy(array, iterator(item,callback(err,result)), callback(err,results)) var arr = [3,6,1]; +/** + * 通过异步迭代器,对集合进行排序 + */ async.sortBy(arr, function(item, callback) { setTimeout(function() { callback(null,item); @@ -21,6 +24,9 @@ async.sortBy(arr, function(item, callback) { // 26.562> 1.1 err: null // 26.562> 1.1 results: [ 1, 3, 6 ] +/** + * 迭代出错,callback返回err,没有results + */ async.sortBy(arr, function(item, callback) { setTimeout(function() { if(item===6) callback('myerr'); diff --git a/t.js b/t.js index 71b9e33..65bb4c7 100644 --- a/t.js +++ b/t.js @@ -1,6 +1,10 @@ +// 其实这个文件名的't'我不是很明白原作者freewind的意思,我觉得叫做'lib.js'或者 +// 'helper.js'比较合适,因为这里面都是些辅助函数。 + var moment = require('moment'); exports.inc = function(n, callback, timeout) { + //将参数n自增1之后的结果返回给async timeout = timeout || 200; setTimeout(function() { callback(null, n+1); @@ -8,6 +12,7 @@ exports.inc = function(n, callback, timeout) { }; exports.fire = function(obj, callback, timeout) { + //直接将obj的内容返回给async timeout = timeout || 200; setTimeout(function() { callback(null, obj); @@ -15,6 +20,7 @@ exports.fire = function(obj, callback, timeout) { }; exports.err = function(errMsg, callback, timeout) { + //模拟一个错误的产生,让async各个函数末尾的callback接收到。 timeout = timeout || 200; setTimeout(function() { callback(errMsg); @@ -23,6 +29,7 @@ exports.err = function(errMsg, callback, timeout) { // utils exports.log = function(msg, obj) { + //对console.log进行了封装。主要是增加了秒钟的输出,通过秒数的差值方便大家对async的理解。 process.stdout.write(moment().format('ss.SSS')+'> '); if(obj!==undefined) { process.stdout.write(msg); @@ -33,6 +40,7 @@ exports.log = function(msg, obj) { }; exports.wait = function(mils) { + //刻意等待mils的时间,mils的单位是毫秒。 var now = new Date; while(new Date - now <= mils); -} \ No newline at end of file +} diff --git a/times.js b/times.js new file mode 100644 index 0000000..dc9d072 --- /dev/null +++ b/times.js @@ -0,0 +1,75 @@ +var async = require('async'); +var t = require('./t'); +var log = t.log; + +/** +* 异步运行,times可以指定调用几次,并把结果合并到数组中返回 +*/ +// times(n, callback) + +function delay(n){return (n+12) % 7 *100;} +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id, + delay:delay(id) + }) +} + +/** + * 异步执行,调用3次createUser函数,结果被合并到数组返回 + */ +//1.1 +async.times(3, function(n, callback){ + log("1.1 enter: "+ n); + setTimeout(function(){ + log('1.1 handler: ',n); + createUser(n, function(err, user) { + callback(err, user) + }) + },delay(n)); +}, function(err, users) { + log('1.1 err: ',err); + log('1.1 result: ',users); +}); +//07.397> 1.1 enter: 0 +//07.400> 1.1 enter: 1 +//07.401> 1.1 enter: 2 +//07.412> 1.1 handler: 2 +//07.912> 1.1 handler: 0 +//08.009> 1.1 handler: 1 +//08.010> 1.1 err: null +//08.011> 1.1 result: [ { id: 'user0', delay: 500 }, +// { id: 'user1', delay: 600 }, +// { id: 'user2', delay: 0 } ] + +/** +* timesSeries与time唯一不同的是,同步执行 +*/ +//timesSeries(n, callback) + +/** + * 同步执行,调用3次createUser函数,结果被合并到数组返回 + */ +//1.2 +async.timesSeries(3, function(n, callback){ + log("1.2 enter: "+ n); + setTimeout(function(){ + log('1.2 handler: ',n); + createUser(n, function(err, user) { + callback(err, user) + }) + },delay(n)); +}, function(err, users) { + log('1.2 err: ',err); + log('1.2 result: ',users); +}); +//16.642> 1.2 enter: 0 +//17.159> 1.2 handler: 0 +//17.162> 1.2 enter: 1 +//17.763> 1.2 handler: 1 +//17.767> 1.2 enter: 2 +//17.778> 1.2 handler: 2 +//17.779> 1.2 err: null +//17.780> 1.2 result: [ { id: 'user0', delay: 500 }, +// { id: 'user1', delay: 600 }, +// { id: 'user2', delay: 0 } ] \ No newline at end of file diff --git a/utils.js b/utils.js index 04e40f7..b1d974c 100644 --- a/utils.js +++ b/utils.js @@ -1,97 +1,122 @@ var async = require('async'); var t = require('./t'); +var log = t.log; /** - * 让某一个函数在内存中缓存它的计算结果。对于相同的参数,只计算一次,下次就直接拿到之前算好的结果。 - */ +* 让某一个函数在内存中缓存它的计算结果。对于相同的参数,只计算一次,下次就直接拿到之前算好的结果。 +* hasher可以让我们自定义如何根据参数来判断它是否已经在缓存中了。 +*/ // memoize(fn, [hasher]) - +//1.1 var slow_fn = function(x, y, callback) { - console.log('start working for: ' + x+','+y); - t.wait(100); - console.log('finished: ' + x+','+y); - callback(null, 'im slow for: '+x+','+y); + log('1.1 start working for: ' + x+','+y); + t.wait(500); + log('1.1 finished: ' + x+','+y); + callback(null, x+','+y); }; - -var fn = async.memoize(slow_fn); - +var fn = async.memoize(slow_fn,function(x,y) { + return x+y; +}); fn('a','b', function(err, result) { - console.log(result); + log("1.1 first time: "+result); +}); +fn('cc','d', function(err, result) { + log("1.1 first time: "+result); }); - -// 直接得到之前计算好的值 fn('a','b', function(err, result) { - console.log(result); + log("1.1 second time: "+result); }); +//15.416> 1.1 start working for: a,b +//15.920> 1.1 finished: a,b +//15.920> 1.1 first time: a,b +//15.921> 1.1 start working for: cc,d +//16.423> 1.1 finished: cc,d +//16.423> 1.1 first time: cc,d +//16.424> 1.1 second time: a,b + /** - * hasher可以让我们自定义如何根据参数来判断它是否已经在缓存中了。 - */ -var fn_hasher = async.memoize(slow_fn, function(x,y) { +* 让已经被缓存的函数,返回不缓存的函数引用。 +*/ +// unmemoize(fn) +//1.2 +var slow_fn2 = function(x, y, callback) { + log('1.2 start working for: ' + x+','+y); + t.wait(500); + log('1.2 finished: ' + x+','+y); + callback(null, x+','+y); +}; +var fn2 = async.memoize(slow_fn2,function(x,y) { return x+y; }); -fn_hasher('cd','e', function(err, result) { - console.log(result); -}); - -fn_hasher('c','de', function(err, result) { - console.log(result); // 可以取得前面('cd','e')的计算结果 - // im show for: cd,e +fn2('a','b', function(err,result) { + log("1.2 first time: "+result); }); +var unFn2 =async.unmemoize(fn2); +log('1.2 unmemoized'); -/** - * 让一个已经被memoize的函数不再缓存结果。 - */ -// unmemoize(fn) - -var fn2 = async.unmemoize(fn); -console.log('unmemoized'); - -fn2('a','b', function(err,result) { - console.log(result); +unFn2('a','b', function(err,result) { + log("1.2 second time: "+result); }); +//16.424> 1.2 start working for: a,b +//16.926> 1.2 finished: a,b +//16.926> 1.2 first time: a,b +//16.927> 1.2 unmemoized +//16.927> 1.2 start working for: a,b +//17.428> 1.2 finished: a,b +//17.428> 1.2 second time: a,b /** - * 执行某异步函数,并记录它的返回值。试验函数时很方便,不用写那些固定模式的代码。 - * - * 如果该函数向回调中传入了多个参数,则每行记录一个。 - */ +* 执行某异步函数,并记录它的返回值。试验函数时很方便,不用写那些固定模式的代码。 +* 如果该函数向回调中传入了多个参数,则每行记录一个。 +*/ // log(function, arguments) - +//1.3 var x = function() { - this.name = 'Freewind'; + this.name = 'bsspirit'; } var hello = function(name, callback) { setTimeout(function() { - callback(null, 'hello ' + name, 'nice to see you ' + name, x, {a:'123'}); + callback(null, + 'first ' + name, + 'second '+ name, + x, + {a:'123'} + ); }, 200); }; +log("1.3 handler"); +async.log(hello, 'time'); +//37.620> 1.3 handler +//first time +//second time +//[Function] +//{ a: '123' } -async.log(hello, 'world'); -// it prints: -// hello world -// nice to see you world -// [Function] -// { a: '123' } - -// 我不太明白dir与log之间,到底有什么大的差别。 -// http://stackoverflow.com/questions/10636866/whats-the-difference-between-async-log-and-async-dir +/** +* dir与log都是打印出输,在nodejs环境中没有分别。 +* dir的不同之处在于,会调用浏览器的console.dir()函数,显示为DOM视图。 +* +* http://stackoverflow.com/questions/10636866/whats-the-difference-between-async-log-and-async-dir +*/ +//1.4 +log("1.4 handler"); async.dir(hello, 'world'); -// it prints: -// 'hello world' -// 'nice to see you world' -// [Function] -// { a: '123' } +//37.620> 1.4 handler +//first time +//second time +//[Function] +//{ a: '123' } /** - * noConflict()仅仅用于浏览器端,在nodejs中没用,这里无法演示。 - * - * 它的作用是:如果之前已经在全局域中定义了async变量,当导入本async.js时,会先把之前的async变量保存起来,然后覆盖它。用完之后,调用noConflict()方法,就会归还该值。同时返回async本身供换名使用。 - */ +* noConflict()仅仅用于浏览器端,在nodejs中没用,这里无法演示。 +* +* 它的作用是:如果之前已经在全局域中定义了async变量,当导入本async.js时,会先把之前的async变量保存起来,然后覆盖它。 + * 用完之后,调用noConflict()方法,就会归还该值。同时返回async本身供换名使用。 +*/ // noConflict() - /* // global on the server, window in the browser var root = this, diff --git a/waterfall.js b/waterfall.js index ddf938b..e6ef0b4 100644 --- a/waterfall.js +++ b/waterfall.js @@ -1,7 +1,10 @@ var async = require('async'); +var t = require('./t'); +var log = t.log; /** - * 按顺序依次执行一组函数。每个函数产生的值,都将传给下一个。如果中途出错,后面的函数将不会被执行。错误信息以及之前产生的结果,将传给waterfall最终的callback。 + * 按顺序依次执行一组函数。每个函数产生的值,都将传给下一个。 + * 如果中途出错,后面的函数将不会被执行。错误信息将传给waterfall最终的callback。之前产生的结果被丢弃。 * * 这个函数名为waterfall(瀑布),可以想像瀑布从上到下,中途冲过一层层突起的石头。 * @@ -9,9 +12,6 @@ var async = require('async'); */ // async.waterfall(tasks, [callback]); -var t = require('./t'); -var log = t.log; - /** * 所有函数正常执行,每个函数的结果都将变为下一个函数的参数。 * @@ -23,33 +23,44 @@ async.waterfall([ function(n, cb) { log('1.1.2: ',n); t.inc(n, cb); }, function(n, cb) { log('1.1.3: ',n); t.fire(n*n, cb); } ], function (err, result) { - log('1.1 err: ', err); // -> null - log('1.1 result: ', result); // -> 16 + log('1.1 err: ', err); + log('1.1 result: ', result); }); +//31.749> 1.1.1: start +//31.752> 1.1.2: 3 +//31.953> 1.1.3: 4 +//32.156> 1.1 err: null +//32.159> 1.1 result: 16 /** - * 中途有函数出错,其err和产生的值将直接传给最终callback,后面的函数不再执行。 - */ +* 中途有函数出错,其err直接传给最终callback,结果被丢弃,后面的函数不再执行。 +*/ // 1.2 async.waterfall([ function(cb) { log('1.2.1: ', 'start'); cb(null, 3); }, function(n, cb) { log('1.2.2: ', n); t.inc(n, cb); }, function(n, cb) { log('1.2.3: ', n); t.err('myerr', cb); }, - function(n, cb) { log('1.2.4: ', n); t.fire(n, cb); } + function(n, cb) { log('1.2.4: ', n); t.fire(n, cb); } ], function (err, result) { - log('1.2 err: ', err); // -> myerr - log('1.2 result: ', result); // -> undefined + log('1.2 err: ', err); + log('1.2 result: ', result); }); +//44.935> 1.2.1: start +//44.939> 1.2.2: 3 +//45.140> 1.2.3: 4 +//45.344> 1.2 err: myerr +//45.348> 1.2 result: /** - * 注意: 以json形式传入tasks,将不会被执行!! - */ +* 注意: 以json形式传入tasks,将不会被执行!! +*/ async.waterfall({ - // these tasks won't be invoked a: function(cb) { log('1.3.1: ', 'start'); cb(null, 3); }, b: function(n, cb) { log('1.3.2: ', n); t.inc(n, cb); }, c: function(n, cb) { log('1.3.3: ', n); t.fire(n*n, cb); } }, function (err, result) { - log('1.3 err: ', err); // -> undefined - log('1.3 result: ', result); // -> undefined -}); \ No newline at end of file + log('1.3 err: ', err); + log('1.3 result: ', result); +}); +//49.222> 1.3 err: [Error: First argument to waterfall must be an array of functions] +//49.228> 1.3 result: \ No newline at end of file diff --git a/whilst_until.js b/whilst_until.js index 3dd933d..a4a5e9d 100644 --- a/whilst_until.js +++ b/whilst_until.js @@ -18,14 +18,12 @@ var log = t.log; * 该函数的功能比较简单,条件变量通常定义在外面,可供每个函数访问。在循环中,异步调用时产生的值实际上被丢弃了,因为最后那个callback只能传入错误信息。 * * 另外,第二个函数fn需要能接受一个函数cb,这个cb最终必须被执行,用于表示出错或正常结束。 - * */ // whilst(test, fn, callback) - /** - * 正常情况,没有出错。第二个函数虽然是异步调用,但被同步执行。所以第三个函数被调用时,已经过了3秒。 - */ +* 正常情况,没有出错。第二个函数虽然是异步调用,但被同步执行。所以第三个函数被调用时,已经过了3秒。 +*/ // 1.1 var count1 = 0; async.whilst( @@ -37,13 +35,18 @@ async.whilst( }, function(err) { // 3s have passed - log('1.1 err: ', err); // -> undefined + log('1.1 err: ', err); } ); +//10.318> 1.1 count: 0 +//11.330> 1.1 count: 1 +//12.342> 1.1 count: 2 +//13.356> 1.1 err: + /** - * 中途出错。出错后立刻调用第三个函数。 - */ +* 中途出错。出错后立刻调用第三个函数。 +*/ // 1.2 var count2 = 0; async.whilst( @@ -59,41 +62,138 @@ async.whilst( }, function(err) { // 2s have passed - log('1.2 err: ', err); // -> myerr + log('1.2 err: ', err); } ); +//12.805> 1.2 count: 0 +//13.824> 1.2 count: 1 +//14.026> 1.2 err: myerr /** - * 第二个函数即使产生值,也会被忽略。第三个函数只能得到err。 - */ +* 第二个函数即使产生值,也会被忽略。第三个函数只能得到err。 +*/ // 1.3 var count3 = 0; async.whilst( - function() { return count3 < 3 }, + function() {return count3 < 3 }, function(cb) { log('1.3 count: ', count3); t.inc(count3++, cb); }, function(err,result){ // result没有用 - log('1.3 err: ', err); // -> undefined - log('1.3 result: ', result); // -> undefined + log('1.3 err: ', err); + log('1.3 result: ', result); } ); +//45.311> 1.3 count: 0 +//45.514> 1.3 count: 1 +//45.718> 1.3 count: 2 +//45.920> 1.3 err: +//45.923> 1.3 result: /** - * until与whilst正好相反,当test为false时循环,与true时跳出。其它特性一致。 - */ -// 1.4 +* doWhilst交换了fn,test的参数位置,先执行一次循环,再做test判断。 和javascript中do..while语法一致。 +*/ +// doWhilst(fn, test, callback) +//1.4 var count4 = 0; -async.until( - function() { return count4>3 }, +async.doWhilst( function(cb) { log('1.4 count: ', count4); - count4++; + t.inc(count4++, cb); + }, + function() { log("1.4 test"); return count4 < 3 }, + function(err,result){ // result没有用 + log('1.4 err: ', err); + log('1.4 result: ', result); + } +); +//33.643> 1.4 count: 0 +//33.848> 1.4 test +//33.850> 1.4 count: 1 +//34.054> 1.4 test +//34.057> 1.4 count: 2 +//34.269> 1.4 test +//34.270> 1.4 err: +//34.270> 1.4 result: + +/** +* until与whilst正好相反,当test为false时循环,与true时跳出。其它特性一致。 +*/ +// 1.5 +var count5 = 0; +async.until( + function() { return count5>3 }, + function(cb) { + log('1.5 count: ', count5); + count5++; setTimeout(cb, 200); }, function(err) { // 4s have passed - log('1.4 err: ',err); // -> undefined + log('1.5 err: ',err); } -); \ No newline at end of file +); +//42.498> 1.5 count: 0 +//42.701> 1.5 count: 1 +//42.905> 1.5 count: 2 +//43.107> 1.5 count: 3 +//43.313> 1.5 err: + +/** +* doUntil与doWhilst正好相反,当test为false时循环,与true时跳出。其它特性一致。 +*/ +// doUntil(fn, test, callback) +// 1.6 +var count6 = 0; +async.doUntil( + function(cb) { + log('1.6 count: ', count6); + count6++; + setTimeout(cb, 200); + }, + function() { log('1.6 test');return count6>3 }, + function(err) { + // 4s have passed + log('1.6 err: ',err); + } +); +//41.831> 1.6 count: 0 +//42.035> 1.6 test +//42.037> 1.6 count: 1 +//42.241> 1.6 test +//42.244> 1.6 count: 2 +//42.456> 1.6 test +//42.457> 1.6 count: 3 +//42.660> 1.6 test +//42.661> 1.6 err: + +/** + * forever,无论条件循环执行,如果不出错,callback永远不被执行 + */ +//forever(fn, callback) +//1.7 +var count7 = 0; +async.forever( + function(cb) { + log('1.7 count: ', count7); + count7++; + setTimeout(cb, 200); + }, + function(err) { + log('1.7 err: ',err); + } +); +//52.770> 1.7 count: 0 +//52.973> 1.7 count: 1 +//53.175> 1.7 count: 2 +//53.377> 1.7 count: 3 +//53.583> 1.7 count: 4 +//53.785> 1.7 count: 5 +//53.987> 1.7 count: 6 +//54.189> 1.7 count: 7 +//54.391> 1.7 count: 8 +//54.593> 1.7 count: 9 +//54.795> 1.7 count: 10 +//54.997> 1.7 count: 11 +//55.199> 1.7 count: 12 \ No newline at end of file