async = require('async');
var documents = ['a', 'b', 'c', 'd', 'e', 'f'];
async.forEachLimit(documents, 2, function(item, callback) {
console.log(".", item);
callback(null);
}, function(err){
console.log("end", err);
});
рд▓реЙрдЧ
$ node test.js
. a
. a
. a
. a
. a
. a
end undefined
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
. b
[...]
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
RangeError: Maximum call stack size exceeded
forEachLimit
рдЧрд▓рдд рд▓рдЧрддрд╛ рд╣реИред
started += 1
running += 1
рдЗрдЯрд░реЗрдЯрд░ рдХреЙрд▓ рдХреЗ рд╕рд╛рдордиреЗ рд▓реЗ рдЬрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред arr[started]
рдХреЛ рднреА arr[started - 1]
. рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
рдиреЛрдЯ: рдЖрдк рдХреЗрд╡рд▓ рдЗрд╕ рдмрдЧ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░реЗрдВрдЧреЗ рдпрджрд┐ рдЗрдЯрд░реЗрдЯрд░ рдЗрдЯрд░реЗрдЯрд░ рдХреЗ рдЕрдВрджрд░ рдХреЛрдб рдЙрд╕реА рдЯрд┐рдХ рдореЗрдВ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
async.js рдореЗрдВ SYNC рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░реЗрдВ
рдореБрдЭреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рдЬрдм рдореЗрд░реЗ рдЗрдЯрд░реЗрдЯрд░ рдореЗрдВ рд╕рд╢рд░реНрдд return callback(null);
рдерд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдерд╛ рдХрд┐ рдореБрдЭреЗ рдмреЗрд╣рддрд░ рдХрд╛рдо рдХрд░рдирд╛ рдерд╛, рдЬреЛ Array.filter
рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╕рд░рдгреА рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдирд╛ рд╣реИ async.forEach
, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорджрджрдЧрд╛рд░ рдерд╛ ...
рдЕрдЧрд░ рдЖрдкрдХреЛ _рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рддреЛ рдЖрдк process.nextTick(function() { callback(); })
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
@jacobrask рдЗрд╕рдиреЗ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ред рдзрдиреНрдпрд╡рд╛рдж
callback(null);
рдХрд░рдирд╛ рд╕рдордХрд╛рд▓рд┐рдХ рд╣реИред рдЖрдкрдХреЛ рдЗрд╕реЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, ala process.nextTick(callback)
, рдпрд╛ process.nextTick(function() { callback(null); });
ред рдЬреИрд╕реЗ @bobrik рдиреЗ рдХрд╣рд╛, async рдореЗрдВ рд╕рд┐рдВрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░реЗрдВ :)
рдпрд╣ рдХрд╣рдирд╛ рдХрд┐ "рдПрд╕рд┐рдВрдХ рдореЗрдВ рд╕рд┐рдВрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░реЗрдВ" рдмрд┐рдВрджреБ рдЧрд╛рдпрдм рд╣реИ - рдпрд╣ рдЯреВрдЯрд╛ рд╣реБрдЖ рд╣реИ, рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ forEachLimit рдореЗрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдореБрджреНрджрд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред
async.forEachLimit(['a','b'], 1, function(item, callback){
if(something) {
doStuff(function(){ callback(); });
} else {
callback();
}
});
рдЬрдмрдХрд┐ рдореИрдВ рдЙрд╕ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЦрд┐рд▓рд╛рдл рдХрд╛рдлреА рдЖрд╕рд╛рди рд╕реБрд░рдХреНрд╖рд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ (рдЬреИрд╕рд╛ рдХрд┐ @jacobrask рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддрд╛ рд╣реИ), рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ doStuff() (рдЬреЛ рдореЗрд░реЗ рдирд┐рдпрдВрддреНрд░рдг рд╕реЗ рдмрд╛рд╣рд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ) рдмрд┐рдирд╛ рдХрд┐рд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдореЗрд░реЗ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддрд╛ рд╣реИред рдЕрдЧрд▓реА рдЯрд┐рдХ ()?
рдореИрдВрдиреЗ async.nextTick рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдХреЛрдб рдЬреЛрдбрд╝рд╛ рд╣реИ рдпрджрд┐ рдпрд╣ рдПрдХ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдЗрдЯрд░реЗрдЯрд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ рдЬреЛ рдЗрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлрд╝реНрд▓реЛ рд╕реЗ рдмрдЪрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдЧрдВрднреАрд░рддрд╛ рд╕реЗ, ASYNC рдореЗрдВ рд╕рд┐рдВрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░реЗрдВ! ... рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓рдЧрд╛рддрд╛рд░ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдпрд╛ рд▓рдЧрд╛рддрд╛рд░ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдмрдирд╛рдПрдВ;)
рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП async.eachSeries
рдХреЗ рд╕рд╛рде рднреА рд╣реБрдЖред
рдЗрд╕рдореЗрдВ рднреА рд╣реЛрддрд╛ рд╣реИ mapLimit
, рдФрд░ рд╣рд╛рдБ рдореЗрд░рд╛ рдлрд╝рдВрдХреНрд╢рди рд╕рд┐рдВрдХ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рдирдХрд▓реА рдлрд╝рдВрдХреНрд╢рди рд╣реИред рдлрд┐рд░ рдореИрдВ рдЗрд╕реЗ setImmediate
рдореЗрдВ рд▓рдкреЗрдЯрддрд╛ рд╣реВрдВ, рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЧрдИред
рдореЗрд░реЗ рд╕рд╛рде async.forEachOfLimit
. рдкрд░ рд╣реБрдЖ
async.waterfall
рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИред
async.queue, рднреА, рдмрд┐рд▓реНрдХреБрд▓ред
рдореИрдВ рдПрдХ рд╕рд┐рдВрдХ рдСрдкрд░реЗрд╢рди рдХрд░ рд░рд╣рд╛ рдерд╛ред рдореИрдВрдиреЗ рдЗрд╕реЗ рдмрджрд▓рдХрд░ рддрдп рдХрд┐рдпрд╛:
callback();
рдкреНрд░рддрд┐
setTimeout(callback, 0);
рдпрд╣ рдореЗрд░реЗ рд╕рд╛рде рддрдм рд╣реБрдЖ рдЬрдм рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд╛рджреЗ рд╕реЗ рдЬреБрдбрд╝рд╛ рдПрдХ рдХреИрдЪ рдерд╛ред рдХреБрдЫ рдЗрд╕ рддрд░рд╣:
async.forEach(items, (item:any, callback:Function) => {
someAsyncPromise(item).then(() => {
callback();
}).catch((err) => {
//console error or something here
callback();
})
});
рдХреИрдЪ рдХреЛ рд╡рд╛рджреЗ рдореЗрдВ async рдмрд┐рдЯ рд╕реЗ рдкрд╣рд▓реЗ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддреНрд░реБрдЯрд┐ рдХреЗрд╡рд▓ рддрднреА рдлреЗрдВрдХреА рдЬрд╛рддреА рд╣реИ рдЬрдм рд╡рд╛рджреЗ рдореЗрдВ рдЕрдкрд╡рд╛рдж рд╣реБрдЖ рд╣реЛред
`
рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдореЗрдВ рд╕рд┐рдВрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ async рдореЗрдВ рдХреЙрд▓ рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред
рд▓реЗрдХрд┐рди, рдЕрдЧрд░ async рдмреЙрдбреА рдХреЗ рдЕрдВрджрд░ рд╕рд┐рдВрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓рдмреИрдХ() рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЧрд▓рдд рд╣реИ, рддреЛ async рдкреНрд░рд▓реЗрдЦрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдРрд╕рд╛ рдХреНрдпреЛрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИ?
рдХреНрдпрд╛ рдХреЛрдИ рдореБрдЭреЗ рдпрд╣ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп async рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ 'рдЙрдЪрд┐рдд' рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ?
рдпрд╣рд╛рдБ рд╕реАрдзреЗ async рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
// assuming openFiles is an array of file names
async.each(openFiles, function(file, callback) {
// Perform operation on file here.
console.log('Processing file ' + file);
if( file.length > 32 ) {
console.log('This file name is too long');
callback('File name too long');
} else {
// Do work to process file here
console.log('File processed');
callback();
}
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
https://caolan.github.io/async/docs.html#each
рдзрдиреНрдпрд╡рд╛рдж!
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдореИрдВ рдПрдХ рд╕рд┐рдВрдХ рдСрдкрд░реЗрд╢рди рдХрд░ рд░рд╣рд╛ рдерд╛ред рдореИрдВрдиреЗ рдЗрд╕реЗ рдмрджрд▓рдХрд░ рддрдп рдХрд┐рдпрд╛:
рдкреНрд░рддрд┐