Async: async.forEachLimit์„ ์‚ฌ์šฉํ•˜๋Š” '์ตœ๋Œ€ ํ˜ธ์ถœ ์Šคํƒ ํฌ๊ธฐ ์ดˆ๊ณผ'

์— ๋งŒ๋“  2011๋…„ 12์›” 26์ผ  ยท  15์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: caolan/async

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

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋™๊ธฐํ™” ์ž‘์—…์„ ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์—์„œ ๋ณ€๊ฒฝํ•˜์—ฌ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

callback();

์—๊ฒŒ

setTimeout(callback, 0);

๋ชจ๋“  15 ๋Œ“๊ธ€

forEachLimit ์ด ์ž˜๋ชป๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

started += 1 running += 1

iterator ํ˜ธ์ถœ ์•ž์œผ๋กœ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. arr[started] ๋„ arr[started - 1] ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ : iterator iterator ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๊ฐ€ ๋™์ผํ•œ ํ‹ฑ์—์„œ ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ด ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

async.js์—์„œ SYNC ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ค‘์ง€

๋‚ด ๋ฐ˜๋ณต๊ธฐ์— ์กฐ๊ฑด๋ถ€ return callback(null); ๊ฐ€ ์žˆ์„ ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. async.forEach #$ ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์— Array.filter ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด์„ ํ•„ํ„ฐ๋งํ•˜๋Š” ๋” ๋˜‘๋˜‘ํ•œ ์ผ์„ ํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค...

ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค๋ฉด 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์—์„œ SYNC ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ค‘์ง€ํ•˜์‹ญ์‹œ์˜ค! ... ๋Œ€์‹  ์ผ๊ด€๋˜๊ฒŒ ๋™๊ธฐ์‹ ๋˜๋Š” ์ผ๊ด€๋˜๊ฒŒ ๋น„๋™๊ธฐ์‹์œผ๋กœ ๊ธฐ๋Šฅ์„ ๋งŒ๋“œ์‹ญ์‹œ์˜ค. ;)

์ด๊ฒƒ์€ 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(); }) });

์ด ์˜ค๋ฅ˜๋Š” promise์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— catch๋Š” promise์˜ ๋น„๋™๊ธฐ ๋น„ํŠธ ์ „์— throw๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

`

๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋น„๋™๊ธฐ์‹์œผ๋กœ ๋™๊ธฐํ™” ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ค‘๋‹จํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋น„๋™๊ธฐ ๋ณธ๋ฌธ ๋‚ด์—์„œ ๋™๊ธฐํ™” ํ•จ์ˆ˜ 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

๊ฐ์‚ฌ ํ•ด์š”!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰