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]
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅. ΠΡ ΡΡΠΎΠ»ΠΊΠ½Π΅ΡΠ΅ΡΡ Ρ ΡΡΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ ΡΠΎΠ»ΡΠΊΠΎ Π² ΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, Π΅ΡΠ»ΠΈ ΠΊΠΎΠ΄ Π²Π½ΡΡΡΠΈ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ° iterator Π²ΡΠ·ΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ°ΡΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² Π² ΡΠΎΠΌ ΠΆΠ΅ ΡΠ°ΠΊΡΠ΅.
ΠΠ ΠΠΠ ΠΠ’ΠΠ’Π¬ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΉ SYNC Π² async.js
Π― ΡΡΠΎΠ»ΠΊΠ½ΡΠ»ΡΡ Ρ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΠΉ, ΠΊΠΎΠ³Π΄Π° Ρ ΠΌΠ΅Π½Ρ Π±ΡΠ»ΠΎ ΡΡΠ»ΠΎΠ²Π½ΠΎΠ΅ return callback(null);
Π² ΠΌΠΎΠ΅ΠΌ ΠΈΡΠ΅ΡΠ°ΡΠΎΡΠ΅. ΠΡΠΎ ΠΎΠ·Π½Π°ΡΠ°Π»ΠΎ, ΡΡΠΎ ΠΌΠ½Π΅ Π½ΡΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ Π±ΠΎΠ»Π΅Π΅ ΡΠΌΠ½ΡΡ Π²Π΅ΡΡ, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΎΡΡΠΈΠ»ΡΡΡΠΎΠ²Π°ΡΡ ΠΌΠ°ΡΡΠΈΠ² Ρ ΠΏΠΎΠΌΠΎΡΡΡ Array.filter
ΠΏΠ΅ΡΠ΅Π΄ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ async.forEach
, ΡΠ°ΠΊ ΡΡΠΎ ΡΡΠΎ Π±ΡΠ»ΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ...
ΠΡΠ»ΠΈ Π²Ρ _Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ_ ΡΡΠΈΡΠ°Π΅ΡΠ΅, ΡΡΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ, Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΎΠ±ΠΎΠΉΡΠΈ ΡΡΠΎ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ process.nextTick(function() { callback(); })
.
@jacobrask ΠΡΠΎ ΡΡΠ°Π±ΠΎΡΠ°Π»ΠΎ Ρ ΠΎΡΠΎΡΠΎ. Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ
ΠΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ callback(null);
ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎ. ΠΠ°ΠΌ Π½ΡΠΆΠ½ΠΎ Π²ΡΠ·ΡΠ²Π°ΡΡ Π΅Π³ΠΎ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎ, Π°Π»Ρ process.nextTick(callback)
ΠΈΠ»ΠΈ process.nextTick(function() { callback(null); });
. ΠΠ°ΠΊ ΡΠΊΠ°Π·Π°Π» @bobrik , ΠΏΡΠ΅ΠΊΡΠ°ΡΠΈΡΠ΅ Π²ΡΠ·ΡΠ²Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π² Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅ :)
Π‘ΠΊΠ°Π·Π°ΡΡ Β«ΠΏΡΠ΅ΠΊΡΠ°ΡΠΈΡΡ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΉ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π² Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅Β» Π½Π΅ Ρ Π²Π°ΡΠ°Π΅Ρ ΡΠΌΡΡΠ»Π° β ΠΎΠ½ Π½Π΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ, ΠΈ ΡΠΎΠ»ΡΠΊΠΎ Π² forEachLimit ΡΡΠΎ ΠΊΠ°ΠΆΠ΅ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΠΉ.
async.forEachLimit(['a','b'], 1, function(item, callback){
if(something) {
doStuff(function(){ callback(); });
} else {
callback();
}
});
Π₯ΠΎΡΡ Ρ ΠΌΠΎΠ³Ρ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ Π·Π°ΡΠΈΡΠΈΡΡΡΡ ΠΎΡ ΡΡΠΎΠ³ΠΎ ΠΎΡΠ΅Π½Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠ° (ΠΊΠ°ΠΊ ΡΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ @jacobrask Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΠΈ), ΡΡΠΎ, Π΅ΡΠ»ΠΈ doStuff() (ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ΅Ρ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡΡ Π² Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ Π²Π½Π΅ ΠΌΠΎΠ΅Π³ΠΎ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ) ΡΠ΅ΡΠΈΡ Π²ΡΠ·Π²Π°ΡΡ ΠΌΠΎΠΉ ΠΎΠ±ΡΠ°ΡΠ½ΡΠΉ Π²ΡΠ·ΠΎΠ² Π±Π΅Π· process.nextTick()?
Π― Π΄ΠΎΠ±Π°Π²ΠΈΠ» Π½Π΅ΠΊΠΎΡΠΎΡΡΠΉ ΠΊΠΎΠ΄ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° 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();
})
});
catch Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ Π²ΡΠ±ΡΠ°Π½ ΠΏΠ΅ΡΠ΅Π΄ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠΌ Π±ΠΈΡΠΎΠΌ Π² ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΈ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΡΡΠ° ΠΎΡΠΈΠ±ΠΊΠ° Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΎΠ³Π΄Π°, ΠΊΠΎΠ³Π΄Π° Π² ΠΎΠ±Π΅ΡΠ°Π½ΠΈΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅.
`
Π― ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ, ΡΡΠΎ ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΡΠ΅ΠΊΡΠ°ΡΠΈΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ Π² Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅.
ΠΠΎ Π΅ΡΠ»ΠΈ Π²ΡΠ·ΠΎΠ² ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ callback() Π²Π½ΡΡΡΠΈ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠ³ΠΎ ΡΠ΅Π»Π° Π½Π΅Π²Π΅ΡΠ΅Π½, ΡΠΎ ΠΏΠΎΡΠ΅ΠΌΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ ΠΏΠΎ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΡΡΠΈ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΡΡΠΎ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ°Ρ ?
ΠΠΎΠΆΠ΅Ρ Π»ΠΈ ΠΊΡΠΎ-Π½ΠΈΠ±ΡΠ΄Ρ ΠΏΠΎΠΌΠΎΡΡ ΠΌΠ½Π΅ ΠΏΠΎΠ½ΡΡΡ, ΠΊΠ°ΠΊ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠΌ ΠΌΠΎΠ΄ΡΠ»Π΅ΠΌ?
ΠΠΎΡ ΠΏΡΠΈΠΌΠ΅Ρ Π½Π΅ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²Π΅Π½Π½ΠΎ ΠΈΠ· Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎΠΉ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ:
// 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
Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ!
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
Π― Π²ΡΠΏΠΎΠ»Π½ΡΠ» ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ. Π― ΠΈΡΠΏΡΠ°Π²ΠΈΠ» ΡΡΠΎ, ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ² Ρ:
ΠΊ