Hola,
Mientras se usa map (...), ¿hay alguna manera al manejar un error emitido por la función iteratee para determinar cuántos elementos aún no se han procesado de la colección proporcionada?
Estoy usando map
para realizar múltiples solicitudes HTTP salientes (usando el nodo request
biblioteca) para una matriz de diferentes urlsparams, etc. En parte al realizar cualquiera de estas solicitudes, puedo obtener un error particular desde el servidor de destino que puedo manejar, pero luego quiero volver a procesar el elemento actual en el que se está trabajando y luego los restantes que map
aún no haya recogido.
Me pregunté si podría establecer una bandera en cada elemento de mi colección en el que se haya trabajado con éxito (sin error), y luego, cuando se emita el error que me interesa, manejarlo en consecuencia. Luego, tal vez cree una nueva matriz a partir de los elementos con la bandera establecida en falso para aquellos que aún no se han procesado y realice map
adicionales sobre estos, asegurándose de invocar la devolución de llamada final original desde el mapa original.
No estoy seguro de si esto tiene algún sentido, pero ¿hay alguna forma de lograr lo que he descrito anteriormente?
Hola @ parky128 , ¡gracias por la pregunta!
¿Funcionaría envolver el iteratee
con reflect
? reflect
siempre pasa un objeto de resultado al callback
, por lo que incluso si uno de los errores de las funciones iteratee
, map
terminaría. Luego, simplemente podría iterar sobre el objeto results
de map
, verificar cuáles tienen una propiedad error
y luego manejarlo en consecuencia. No tendría que volver a procesar ningún artículo que map
no haya recogido.
async.map(coll, async.reflect(function(val, callback) {
// your request code
}, function(err, results) {
// err will always be null now
results.forEach(function(result, i) {
if (result.error) {
// your code for handling errors
// if `coll` is an array, you could access the value that caused
// this error through `coll[i]` as `map` preserves the order for arrays
} else {
// otherwise `result.value` will contain the result of that `iteratee` call
}
});
});
De lo contrario, para responder a su pregunta, map
siempre devuelve un array
. Puede iterar sobre esa matriz y verificar qué valores son undefined
. Esos corresponderán a los artículos que tuvieron errores, pasaron undefined
a sus callback
, estaban en progreso cuando ocurrió el error
o no habían comenzado. Sin embargo, el enfoque reflect
es probablemente la opción más segura, ya que undefined
puede ser un resultado válido de una llamada iteratee
.
Gracias por tomarse el tiempo para ofrecer una posible solución. De hecho, me gustaría que la devolución de llamada final async.map se invocara tan pronto como uno de los errores de funciones iteratee
con el caso de error particular que estoy buscando detectar.
Al mirar los documentos, veo que puedo lograr esto pasando un error a la función de devolución de llamada iteratee, pero me pregunto si en la devolución de llamada final que invocará async.map, si podría usar ese objeto de resultados para comparar con el original recopilación y ver qué queda por procesar.
Simplemente no quiero que async.map intente procesar otras solicitudes tan pronto como una de estas devuelva el caso de error que me interesa.
Simplemente no quiero que async.map intente procesar otras solicitudes tan pronto como una de estas devuelva el caso de error que me interesa.
Suponiendo que su iteratee
es asíncrono, async.map
habrá comenzado a procesar todos los elementos cuando se invoque la devolución de llamada final. Potencialmente, podría comparar el objeto de resultados con la colección para ver qué elementos aún no han terminado de procesarse, pero eso también tiene sus inconvenientes. Por ejemplo, tendría que hacerlo sincrónicamente, en la misma marca se invoca la devolución de llamada final, ya que el objeto de resultados se actualizará como iteratee
s resolve.
Podrías probar mapSeries
. mapSeries
solo ejecutará una solicitud a la vez. es decir, solo llama al siguiente elemento cuando el actual termina de procesarse (en lugar de iniciarlos todos a la vez). Esto significa que cuando ocurre un error y se invoca la devolución de llamada final, no se ejecutarán más iteratee
s. Luego, podría comparar los resultados con la colección para ver qué elementos aún no se han procesado. Esto todavía es una pequeña solución, pero es mejor que usar async.map
. Sin embargo, el principal inconveniente de este enfoque es que las solicitudes ya no se manejan en paralelo.
Por ejemplo, si su colección es una matriz
async.mapSeries(coll, function(val, callback) {
// your iteratee function
}, function(err, results) {
if (err) {
// unprocessItems will include the item that errored.
var unprocessItems = coll.slice(results.length - 1);
// handle the unprocessedItems
}
});
Hmm Ok, sí, mi función iteratee es asincrónica, ya que usa la biblioteca de solicitudes para hacer una solicitud http saliente y devuelvo la llamada con el resultado. Entonces, si digo que tenía 10 elementos para iterar, 4 tuvieron éxito y el quinto falló, lo que luego invocaría la devolución de llamada a la función iteratee con un parámetro de error, si eso significa que el objeto de resultados en la devolución de llamada final a async.map solo contendrá los 4 resultados exitosos?
Si es así, por ahora viviré con el hecho de que seguirá haciendo todas las llamadas salientes. En el futuro, puedo ser un yo para dividir mi matriz en matrices más pequeñas y realizar mapas asíncronos más pequeños dentro de un mapSeries para minimizar el acceso inicial al servidor de destino que reciben las solicitudes.
@hargasinski - Terminé usando el enfoque async.reflect
y esto me está funcionando bien, me brinda una visibilidad completa de todos los elementos que dieron un error: +1:
¡Gracias!
Comentario más útil
Hola @ parky128 , ¡gracias por la pregunta!
¿Funcionaría envolver el
iteratee
conreflect
?reflect
siempre pasa un objeto de resultado alcallback
, por lo que incluso si uno de los errores de las funcionesiteratee
,map
terminaría. Luego, simplemente podría iterar sobre el objetoresults
demap
, verificar cuáles tienen una propiedaderror
y luego manejarlo en consecuencia. No tendría que volver a procesar ningún artículo quemap
no haya recogido.De lo contrario, para responder a su pregunta,
map
siempre devuelve unarray
. Puede iterar sobre esa matriz y verificar qué valores sonundefined
. Esos corresponderán a los artículos que tuvieron errores, pasaronundefined
a suscallback
, estaban en progreso cuando ocurrió elerror
o no habían comenzado. Sin embargo, el enfoquereflect
es probablemente la opción más segura, ya queundefined
puede ser un resultado válido de una llamadaiteratee
.