Async: Async no protege contra modificaciones de matriz durante el tiempo de ejecución de la función

Creado en 4 jul. 2014  ·  6Comentarios  ·  Fuente: caolan/async

Cuando tiene una llamada asincrónica, por ejemplo. async.each , y durante ese tiempo de ejecución, la matriz que se pasa tiene modificaciones, entonces puede que nunca termine, o llamará a la devolución de llamada dos veces.

Ejemplo:

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 ejemplo recorre los 3 elementos de la matriz original e imprime i pero luego nunca llama a la devolución de llamada, porque en async.each está haciendo:

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

Al mirar el código asincrónico, está haciendo una comparación con arr.length que puede cambiar ... ¿no sería mejor almacenar la longitud de la matriz original y hacer una comparación con eso, asegurándose de que se llamará a la devolución de llamada completa? ?

Violín:
http://jsfiddle.net/4ysKX/1/

bug

Comentario más útil

¿Async terminó rechazando las modificaciones de matriz después del hecho? Tengo un caso de uso en el que sería bueno modificar la matriz original después del hecho, para iterar en más elementos que inicialmente.

Todos 6 comentarios

Tienes razón, así que no lo modifiques. Clone su matriz antes de pasarla a una función asíncrona si necesita cambiarla más tarde.

@aearly Sí, es una

Sería difícil protegerse contra _cualquier_ modificación de la matriz sin clonar la entrada, por ejemplo, una modificación síncrona en la función del iterador, pero la protección contra la modificación _asincrónica_ no relacionada con la iteración debería ser sencilla incluso sin clonar; en realidad, no suponiendo arr.length permanecerá constante después de activar los trabajos asíncronos (guardando la longitud en una variable antes de la iteración).

(Trabajo con @bradens - uno de nosotros enviará un PR con pruebas si eso es bienvenido).

Un PR con pruebas sería bienvenido, pero en última instancia depende de @caolan fusionarlo.

La desventaja de hacer esto es la sobrecarga adicional de la copia de la matriz. Si tiene una matriz grande, o está llamando a async.each et al muchas veces, será más lento y usará más memoria.

Estoy de acuerdo en que una copia de matriz sería demasiada sobrecarga. Estoy sugiriendo que dado que la iteración inicial de la matriz es síncrona, la longitud de la matriz original podría guardarse para verificar más adelante. De esa manera, la cantidad de llamadas de devolución de llamada coincidirá con la cantidad de llamadas de iterador, incluso si la matriz se cambia mientras tanto. Esto debería ser fácil y sin gastos generales para async.each , pero aún no he examinado las otras funciones. Sería bueno si todas las funciones paralelas tuvieran un comportamiento consistente en estos casos.

Este es un duplicado del # 557.

¿Async terminó rechazando las modificaciones de matriz después del hecho? Tengo un caso de uso en el que sería bueno modificar la matriz original después del hecho, para iterar en más elementos que inicialmente.

¿Fue útil esta página
0 / 5 - 0 calificaciones