Async: Async não protege contra modificações de array durante o tempo de execução da função

Criado em 4 jul. 2014  ·  6Comentários  ·  Fonte: caolan/async

Quando você tem uma chamada assíncrona, por exemplo. async.each , e durante esse tempo de execução, o array que é passado tem modificações, então pode nunca terminar ou irá chamar o callback duas vezes.

Exemplo:

async = require "async" 
arr = [1, 2, 3]  
async.each arr, ((i, cb) -> console.log "i"; setImmediate(cb)), (err) -> console.log "done" 
arr.push(4)

Este exemplo percorre os 3 elementos da matriz original e imprime i mas nunca chama o retorno de chamada, porque em async.each está fazendo:

if (completed >= arr.length) {
  callback(null);
}

Ao olhar para o código assíncrono, ele está fazendo uma comparação com arr.length que pode mudar ... não seria melhor armazenar o comprimento do array original e fazer uma comparação com ele, garantindo que o retorno de chamada concluído será chamado ?

Violino:
http://jsfiddle.net/4ysKX/1/

bug

Comentários muito úteis

Async acabou desautorizando modificações de array depois do fato? Eu tenho um caso de uso em que seria bom modificar o array original após o fato, de modo a iterar em mais elementos do que inicialmente.

Todos 6 comentários

Você está certo - então não o modifique. Clone sua matriz antes de passá-la para uma função assíncrona se precisar alterá-la mais tarde.

@aearly Sim, isso é uma

Seria difícil se proteger contra _qualquer_ modificação de array sem clonar a entrada, por exemplo, uma modificação síncrona na função do iterador, mas a proteção contra modificação _assíncrona_ não relacionada à iteração deve ser direta, mesmo sem clone - na verdade, apenas não assumindo arr.length permanecerá constante após girar os trabalhos assíncronos (salvando o comprimento em uma variável antes da iteração).

(Eu trabalho com @bradens - um de nós enviará um PR com testes, se for bem-vindo).

Um RP com testes seria bem-vindo, mas, em última análise, cabe a @caolan fazer a fusão.

A desvantagem de fazer isso é a sobrecarga extra da cópia do array. Se você tiver um array grande ou estiver chamando async.each et al muitas vezes, será mais lento e usará mais memória.

Eu concordo que uma cópia do array seria uma sobrecarga muito grande. Estou sugerindo que, como a iteração inicial do array é síncrona, o comprimento do array original pode ser salvo para verificação posterior. Dessa forma, o número de chamadas de retorno corresponderá ao número de chamadas de iterador, mesmo se a matriz for alterada nesse meio tempo. Isso deve ser fácil e zero sobrecarga para async.each , mas eu não olhei para as outras funções ainda. Seria bom se todas as funções paralelas tivessem um comportamento consistente nesses casos.

Esta é uma duplicata de # 557.

Async acabou desautorizando modificações de array depois do fato? Eu tenho um caso de uso em que seria bom modificar o array original após o fato, de modo a iterar em mais elementos do que inicialmente.

Esta página foi útil?
0 / 5 - 0 avaliações