Async: eachSeries com uma chamada assíncrona aninhada resulta em um tamanho máximo de pilha de chamadas excedido

Criado em 10 ago. 2016  ·  3Comentários  ·  Fonte: caolan/async

Qual versão do assíncrono você está usando?

2.0.1

Em qual ambiente o problema ocorreu (versão do nó / versão do navegador)

Nó 6.2.1
NPM 3.9.3

O que você fez?

let counter = 2000;

async.eachSeries(
  new Array(counter),
  (item, cb) => {
    async.parallel([
      (pCb) => {
        console.log(counter--);
        pCb();
      },
    ], cb);
  },
  () => console.log('done')
);

O que você esperava que fosse acontecer?

Eu esperava que cada uma das iterações ocorresse, o que resultaria nos dois últimos console.log sendo '1' e 'concluído'.

Qual foi o resultado real?

Depois de menos de 1000 iterações, receberia este erro:

RangeError: tamanho máximo da pilha de chamadas excedido

Quando voltei para assíncrono 1.5.2, o código acima funcionou conforme o esperado.

question

Comentários muito úteis

O motivo pelo qual isso funcionou no assíncrono 1.5.2 é que garantimos que o retorno de chamada sempre foi chamado de forma assíncrona nessa versão. Na versão 2, removemos essa proteção (consulte https://github.com/caolan/async/blob/master/intro.md#synchronous-iteration-functions)

Portanto, no seu caso, para corrigir o script, você pode usar async.ensureAsync(cb) ou async.setImmediate(cb) para contornar o problema de recursão:

var counter = 2000;

async.eachSeries(
  new Array(counter),
  (item, cb) => {
    async.parallel([
      (pCb) => {
        console.log(counter--);
        async.setImmediate(pCb);
      },
    ], cb);
  },
  () => console.log('done')
);

Todos 3 comentários

+1

+1

O motivo pelo qual isso funcionou no assíncrono 1.5.2 é que garantimos que o retorno de chamada sempre foi chamado de forma assíncrona nessa versão. Na versão 2, removemos essa proteção (consulte https://github.com/caolan/async/blob/master/intro.md#synchronous-iteration-functions)

Portanto, no seu caso, para corrigir o script, você pode usar async.ensureAsync(cb) ou async.setImmediate(cb) para contornar o problema de recursão:

var counter = 2000;

async.eachSeries(
  new Array(counter),
  (item, cb) => {
    async.parallel([
      (pCb) => {
        console.log(counter--);
        async.setImmediate(pCb);
      },
    ], cb);
  },
  () => console.log('done')
);
Esta página foi útil?
0 / 5 - 0 avaliações