async是一个工具模块,其中方法有很多,主要分3大类(集合,流程控制,工具),今天就简单说说 集合 的一些常用方法
each(arr, iterator, callback)
很简单,看方法名就知道这是一个循环。
参数:
-
arr
想要循环的数组 -
iterator(item, callback)
一个回调函数,循环到的每一项都会调用这个函数。item
数组中的每一项。callback(err)
当完成的时候调用,应该不带参数执行,或者明确指定一个null
-
callback(err)
一个回调函数,用于循环完成后 或 发生错误时调用
这个循环与系统提供的for
循环等是一样的。属于并行执行的循环,请看下面的例子:
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log('start:' + item.name);
setTimeout(function(){
console.log('end: ' + item.name);
done(null);
}, item.delay);
}
async.each(arr, iterator, function (err) {
console.log('err: ' + err);
});
输出结果是:
start:a
start:b
start:c
end: b
end: a
end: c
err: undefined
先输出3个 start, 然后输出3个 end 注意顺序, 最后是 err
由此可以看出,它与正常的循环并无两样。
eachSeries(arr, iterator, callback)
语法与上面的用法一样。不同的是,上面我称为 并行执行的循环,而这个我称为,依次执行的循环,请看下面的例子:
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log('start:' + item.name);
setTimeout(function(){
console.log('end: ' + item.name);
done(null);
}, item.delay);
}
async.eachSeries(arr, iterator, function (err) {
console.log('err: ' + err);
});
细心的同学可能已经发现问题了。这段代码与上面的代码几乎一模一样。唯一不一样的地方只有async.each
改成了 async.eachSeries
结果为:
start:a
end: a
start:b
end: b
start:c
end: c
err: undefined
看完结果同学们就可以理解,为什么称 eachSeries
为依次执行的循环了。
eachLimit(arr, limit, iterator, callback)
如果非要起一个名字的话。我称它为 分批执行 也可以说是 限制并行数量的循环
用法与上面大致一样。只不过多了一个参数 limit
limit
限制并行的最大数量
看一下例子:
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log('start:' + item.name);
setTimeout(function(){
console.log('end: ' + item.name);
done(null);
}, item.delay);
}
async.eachLimit(arr, 1, iterator, function (err) {
console.log('err: ' + err);
});
结果为:
start:a
end: a
start:b
end: b
start:c
end: c
err: undefined
可以看出,如果 limit
的为 1
,那么就与 eachSeries
一样,一条一条依次执行。
如果 limit
的数量为 3
我们在试试:
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log('start:' + item.name);
setTimeout(function(){
console.log('end: ' + item.name);
done(null);
}, item.delay);
}
async.eachLimit(arr, 3, iterator, function (err) {
console.log('err: ' + err);
});
输出结果为:
start:a
start:b
start:c
end: b
end: a
end: c
err: undefined
相信同学们已经看明白,我就不多做解释了。
map(arr, iterator, callback)
map
通俗点说,就是通过一个转换函数(iterator),把数组中的每个值映射到一个新的数组中。(产生一个新的数组)
参数:
-
arr
想要循环的数组 -
iterator(item, callback)
一个回调函数,循环到得每一项都会调用这个函数callback(err, transformed)
当程序执行完时,调用此参数(必须调用此参数) -
callback(err, results)
一个回调函数,当所有数组执行完成,或发生错误的时候,被调用。
例如:
function iterator (item, done) {
console.log( 'start:', item.name );
setTimeout(function () {
console.log( 'end:', item.name );
done(null, item.name += '!');
}, item.delay);
}
async.map(arr, iterator, function (err, result) {
console.log( 'err: ', err );
console.log( 'result:', result );
});
结果为:
start: a
start: b
start: c
end: b
end: a
end: c
err: undefined
result: [ 'a!', 'b!', 'c!' ]
mapSeries(arr, iterator, callback)
语法与上面 map
一样,不同的是,上面是 并行执行,而这个是 依次执行,与 each
和 eachSeries
的关系是一样的。
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log( 'start:', item.name );
setTimeout(function () {
console.log( 'end:', item.name );
done(null, item.name += '!');
}, item.delay);
}
async.mapSeries(arr, iterator, function (err, result) {
console.log( 'err: ', err );
console.log( 'result:', result );
});
代码与 map
几乎一样。只是把 async.map
改成了 async.mapSeries
,输出结果为:
start: a
end: a
start: b
end: b
start: c
end: c
err: undefined
result: [ 'a!', 'b!', 'c!' ]
从输出结构可以看出,它是依次执行的。
mapLimit(arr, limit, iterator, callback)
与 map
一样,但比 map
多了一个参数 limit
来限制并行的最大数量。
var arr = [ {name: 'a', delay: 200}, {name: 'b', delay: 100}, {name: 'c', delay: 300} ];
function iterator (item, done) {
console.log( 'start:', item.name );
setTimeout(function () {
console.log( 'end:', item.name );
done(null, item.name += '!');
}, item.delay);
}
async.mapLimit(arr, 1, iterator, function (err, result) {
console.log( 'err: ', err );
console.log( 'result:', result );
});
limit
设置为 1
,结果为:
start: a
end: a
start: b
end: b
start: c
end: c
err: undefined
result: [ 'a!', 'b!', 'c!' ]
结果与 mapSeries
一样,换成 2
结果为:
start: a
start: b
end: b
start: c
end: a
end: c
err: undefined
result: [ 'a!', 'b!', 'c!' ]
换成 3
结果为:
start: a
start: b
start: c
end: b
end: a
end: c
err: undefined
result: [ 'a!', 'b!', 'c!' ]
filter(arr, iterator, callback)
遍历 arr
中的每个值,返回包含所有通过 iterator
真值检测的元素值。这个操作是并行的,但返回的结果是顺序的。
参数:
-
arr
一个数组,用于遍历 -
iterator(item, callback)
一个函数,用于真值检测item
数组中的每一项callback(truthValue)
完成时调用,必须带一个布尔参数 -
callback
一个回调函数,用于执行完成后,或发生错误时调用。
例如:
var arr = [ {n: 1, delay: 200}, {n: 2, delay: 100}, {n: 3, delay: 300}, {n: 4, delay: 500}, {n: 5, delay: 100} ];
function iterator (item, done) {
console.log( 'start:', item.n );
setTimeout(function () {
console.log( 'end:', item.n );
done( item.n > 2 );
}, item.delay);
}
async.filter(arr, iterator, function (result) {
console.log( 'result:', result );
});
输出结果为:
start: 1
start: 2
start: 3
start: 4
start: 5
end: 2
end: 5
end: 1
end: 3
end: 4
result: [ { n: 3, delay: 300 }, { n: 4, delay: 500 }, { n: 5, delay: 100 } ]
filterSeries(arr, iterator, callback)
与上面 filter
类似,它是 依次执行。
var arr = [ {n: 1, delay: 200}, {n: 2, delay: 100}, {n: 3, delay: 300}, {n: 4, delay: 500}, {n: 5, delay: 100} ];
function iterator (item, done) {
console.log( 'start:', item.n );
setTimeout(function () {
console.log( 'end:', item.n );
done( item.n > 2 );
}, item.delay);
}
async.filterSeries(arr, iterator, function (result) {
console.log( 'result:', result );
});
把 async.filter
改成 async.filterSeries
输出结果为:
start: 1
end: 1
start: 2
end: 2
start: 3
end: 3
start: 4
end: 4
start: 5
end: 5
result: [ { n: 3, delay: 300 }, { n: 4, delay: 500 }, { n: 5, delay: 100 } ]
reject(arr, iterator, callback)
reject跟filter正好相反,当检测为true时,抛弃之~~~
var arr = [ {n: 1, delay: 200}, {n: 2, delay: 100}, {n: 3, delay: 300}, {n: 4, delay: 500}, {n: 5, delay: 100} ];
function iterator (item, done) {
console.log( 'start:', item.n );
setTimeout(function () {
console.log( 'end:', item.n );
done( item.n > 2 );
}, item.delay);
}
async.reject(arr, iterator, function (result) {
console.log( 'result:', result );
});
输出结果为:
start: 1
start: 2
start: 3
start: 4
start: 5
end: 2
end: 5
end: 1
end: 3
end: 4
result: [ { n: 1, delay: 200 }, { n: 2, delay: 100 } ]
rejectSeries(arr, iterator, callback)
如果说reject是并行(异步的)的,那么rejectSeries就是串行的(同步的),前面写了那么多 并行 和 串行 的比较例子,从现在往后就不举例说明了。
reduce(arr, memo, iterator, callback)
Reduce可以让我们给定一个初始值,用它与集合中的每一个元素做运算**(前一次的运算结果与下一个值做运算)**,最后得到一个值。reduce从左向右来遍历元素,如果想从右向左,可使用reduceRight。
加法运算:
var arr = [1, 3, 5];
function iterator (memo, item, done) {
console.log( memo, item );
setTimeout(function () {
done( null, item + memo );
}, 300);
}
async.reduce(arr, 2, iterator, function (err, result) {
console.log( 'result:', result );
});
输出结果为:
2 1
3 3
6 5
result: 11
乘法运算:
var arr = [1, 3, 5];
function iterator (memo, item, done) {
console.log( memo, item );
setTimeout(function () {
done( null, item * memo );
}, 300);
}
async.reduce(arr, 2, iterator, function (err, result) {
console.log( 'result:', result );
});
输出结果为:
2 1
2 3
6 5
result: 30
reduceRight(arr, memo, iterator, callback)
与 reduce
一样,不同的是,reduceRight
是从右向左计算。
detect(arr, iterator, callback)
用于取得集合中满足条件的第一个元素(并行执行)。
语法:
-
arr
一个数组 -
iterator(item, callback)
回调函数,用于处理逻辑(迭代器)item
数组中的每一项callback(truthValue)
程序完成后执行。必须传入布尔值。 -
callback(result)
回调函数,iterator
第一次返回true
,或 循环完成后执行。
例如:
var arr = [
{n:1,delay:500},
{n:2,delay:200},
{n:3,delay:300}
];
function iterator (item, done) {
console.log( 'start:', item.n );
setTimeout(function () {
console.log( 'end:', item.n )
done( item.n > 1 );
}, item.delay );
}
async.detect(arr, iterator, function (result) {
console.log( 'result:', result );
});
输出结果为:
start: 1
start: 2
start: 3
end: 2
result: { n: 2, delay: 200 }
end: 3
end: 1
可以看出,输出 2
的时候,就执行 callback(result)
了,也可以看出。detect
是并行执行的。
detectSeries(arr, iterator, callback)
与 detect
类似。不过 detectSeries
是依次执行的。
例如:
var arr = [
{n:1,delay:500},
{n:2,delay:200},
{n:3,delay:300}
];
function iterator (item, done) {
console.log( 'start:', item.n );
setTimeout(function () {
console.log( 'end:', item.n )
done( item.n > 1 );
}, item.delay );
}
async.detectSeries(arr, iterator, function (result) {
console.log( 'result:', result );
});
输出结果为:
start: 1
end: 1
start: 2
end: 2
result: { n: 2, delay: 200 }
sortBy(arr, iterator, callback)
对集合内的元素进行排序,根据每个元素进行某异步操作后产生的值,从小到大排序。
语法:
-
arr
一个数组 -
iterator(item, callback)
一个回调函数,循环到得每一项都会执行。item
数组中的每一项callback(err, sortValue)
完成时调用。 -
callback(err, results)
一个回调函数,所有iterator
完成后或发生错误时执行。
例1:
var arr = [2, 5, 9, 10, 22, 1, 7, 20];
function iterator (item, done) {
done( null, item );
}
async.sortBy(arr, iterator, function (err, result) {
console.log( result ); // [ 1, 2, 5, 7, 9, 10, 20, 22 ]
});
例2:
var arr = [2, 5, 9, 10, 22, 1, 7, 20];
function iterator (item, done) {
done( null, item * -1 );
}
async.sortBy(arr, iterator, function (err, result) {
console.log( result ); // [ 22, 20, 10, 9, 7, 5, 2, 1 ]
});
some(arr, iterator, callback)
判断集合中是否有至少一个元素满足条件,如果是最终callback得到的值为true,否则为false.
参数:
-
arr
一个数组 -
iterator(item, callback)
一个回调函数,循环到得每一项都会执行。callback(truthValue)
必须传递一个布尔值。 -
callback(result)
回调函数result
为true
或false
取决于iterator
的运行结果。
例1:
var arr = [2, 5, 9, 10];
function iterator (item, done) {
done( item > 10 );
}
async.some(arr, iterator, function (result) {
console.log( result ); // false
});
结果是 false
,因为数组中,没有比10大的数。
例2:
var arr = [2, 5, 9, 10];
function iterator (item, done) {
done( item > 9 );
}
async.some(arr, iterator, function (result) {
console.log( result ); // true
});
结果是 true
,因为 10
比 9
大。
every(arr, iterator, callback)
如果集合里每一个元素都满足条件,则传给最终回调的result为true,否则为false
例1:
var arr = [2, 5, 9, 10];
function iterator (item, done) {
done( item > 1 );
}
async.every(arr, iterator, function (result) {
console.log( result ); // true
});
例2:
var arr = [2, 5, 9, 10];
function iterator (item, done) {
done( item > 5 );
}
async.every(arr, iterator, function (result) {
console.log( result ); // false
});
concat(arr, iterator, callback)
将多个异步操作的结果合并为一个数组。
语法:
concat(arr, iterator(item,callback(err, result)), callback(err, result))
code:
var arr = [
{
list : [1,2,3,4],
delay : 200
},{
list : [5,6,7],
delay : 100
},{
list : [8,9],
delay : 300
}
];
function iterator (item, done) {
console.log( 'start:', item.list )
setTimeout(function () {
console.log( 'end:', item.list )
done( null, item.list );
}, item.delay);
}
async.concat(arr, iterator, function (err, result) {
console.log( result ); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
});
结果为:
start: [ 1, 2, 3, 4 ]
start: [ 5, 6, 7 ]
start: [ 8, 9 ]
end: [ 5, 6, 7 ]
end: [ 1, 2, 3, 4 ]
end: [ 8, 9 ]
[ 5, 6, 7, 1, 2, 3, 4, 8, 9 ]
通过结果,会发现。这是一个并行的操作。合并之后的顺序是不固定的。
concatSeries(arr, iterator, callback)
与 concat
类似,不过 concatSeries
是串行的。
code:
var arr = [
{
list : [1,2,3,4],
delay : 200
},{
list : [5,6,7],
delay : 100
},{
list : [8,9],
delay : 300
}
];
function iterator (item, done) {
console.log( 'start:', item.list )
setTimeout(function () {
console.log( 'end:', item.list )
done( null, item.list );
}, item.delay);
}
async.concatSeries(arr, iterator, function (err, result) {
console.log( result ); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
});
结果是:
start: [ 1, 2, 3, 4 ]
end: [ 1, 2, 3, 4 ]
start: [ 5, 6, 7 ]
end: [ 5, 6, 7 ]
start: [ 8, 9 ]
end: [ 8, 9 ]
[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]