Привет,
При использовании map (...) есть ли способ при обработке ошибки, вызванной функцией итератора, определить, сколько элементов еще не было обработано из предоставленной коллекции?
Я использую map
для выполнения нескольких исходящих HTTP-запросов (с использованием библиотеки node request
) для массива различных URL-адресов и т. Д. В процессе выполнения любого из этих запросов я могу получить определенную ошибку с целевого сервера, с которым я могу справиться, но затем я хочу повторно обработать текущий элемент, над которым работает, а затем любые оставшиеся, которые map
еще не подобраны.
Мне было интересно, может быть, установить флаг для каждого элемента в моей коллекции, который был успешно обработан (без ошибок), а затем, когда возникнет ошибка, которая меня интересует, обработайте ее соответствующим образом. Затем, возможно, создайте новый массив из элементов с флагом, установленным в false для тех, которые еще не обработаны, и выполните еще map
над ними, убедившись, что я вызываю исходный окончательный обратный вызов из исходной карты.
Не уверен, имеет ли это какой-то смысл, но есть ли способ достичь того, что я описал выше?
Привет @ parky128 , спасибо за вопрос!
Будет ли работать упаковка iteratee
с reflect
? reflect
всегда передает объект результата в callback
, поэтому, даже если одна из ошибок iteratee
functions, map
завершится. Затем вы можете просто перебрать объект results
из map
, проверить, какие из них имеют свойство error
, а затем обработать его соответствующим образом. Вам не придется повторно обрабатывать предметы, которые map
могли не подобрать.
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
}
});
});
В противном случае, чтобы ответить на ваш вопрос, map
всегда возвращает array
. Вы можете перебрать этот массив и проверить, какие значения равны undefined
. Они будут соответствовать элементам, которые были ошибочными, передали undefined
их callback
, находились в процессе выполнения, когда произошла ошибка error
или не были запущены. Подход reflect
вероятно, является более безопасным вариантом, поскольку undefined
может быть допустимым результатом вызова iteratee
.
Спасибо, что нашли время предложить потенциальное решение. На самом деле я бы хотел, чтобы конечный обратный вызов async.map запускался, как только одна из ошибок iteratee
functions с конкретным случаем ошибки, который я ищу.
Глядя на документы, я вижу, что могу добиться этого, передав ошибку в функцию обратного вызова итерации, но мне интересно, будет ли в последнем обратном вызове, который вызовет async.map, просто использовать этот объект результатов для сравнения с исходным сбор и посмотрите, что осталось обработать.
Я просто не хочу, чтобы async.map пытался обрабатывать любые другие запросы, как только один из них вернет интересующий меня случай ошибки.
Я просто не хочу, чтобы async.map пытался обрабатывать любые другие запросы, как только один из них вернет интересующий меня случай ошибки.
Предполагая, что ваш iteratee
асинхронный, async.map
начнет обработку всех элементов при вызове последнего обратного вызова. Вы можете сравнить объект результатов с коллекцией, чтобы увидеть, какие элементы еще не завершили обработку, но у этого также есть свои подводные камни. Например, вам нужно будет сделать это синхронно, в тот же самый тик будет вызван последний обратный вызов, поскольку объект результатов будет обновлен как разрешение iteratee
s.
Вы можете попробовать mapSeries
. mapSeries
будет запускать только один запрос за раз. т.е. он вызывает следующий элемент только тогда, когда текущий завершает обработку (в отличие от запуска всех сразу). Это означает, что когда возникает ошибка и вызывается последний обратный вызов, больше iteratee
s запускаться не будет. Затем вы можете сравнить результаты с коллекцией, чтобы увидеть, какие элементы еще не были обработаны. Это все еще небольшой обходной путь, но он лучше, чем использование async.map
. Однако основным недостатком этого подхода является то, что запросы больше не обрабатываются параллельно.
Например, если ваша коллекция представляет собой массив
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
}
});
Хм Хорошо, да, моя функция iteratee является асинхронной, поскольку она использует библиотеку запросов для выполнения исходящего HTTP-запроса, и я выполняю обратный вызов от нее с результатом. Итак, если я скажу, что у меня было 10 элементов для итерации, 4 были выполнены успешно, а 5-й не удалось, что я бы затем вызвал обратный вызов функции итерации с параметром ошибки, если это означает, что объект результатов в последнем обратном вызове async.map будет содержать только 4 успешных результата?
Если это так, то пока я буду жить с тем фактом, что он по-прежнему будет выполнять все исходящие звонки. Я могу разделить свой массив на более мелкие массивы и выполнить более мелкие async.maps в mapSeries, чтобы минимизировать начальное попадание на целевой сервер, с которым сталкиваются запросы.
@hargasinski - в async.reflect
и он отлично работает для меня, дает мне полную видимость всех элементов, которые выдавали ошибку: +1:
Спасибо!
Самый полезный комментарий
Привет @ parky128 , спасибо за вопрос!
Будет ли работать упаковка
iteratee
сreflect
?reflect
всегда передает объект результата вcallback
, поэтому, даже если одна из ошибокiteratee
functions,map
завершится. Затем вы можете просто перебрать объектresults
изmap
, проверить, какие из них имеют свойствоerror
, а затем обработать его соответствующим образом. Вам не придется повторно обрабатывать предметы, которыеmap
могли не подобрать.В противном случае, чтобы ответить на ваш вопрос,
map
всегда возвращаетarray
. Вы можете перебрать этот массив и проверить, какие значения равныundefined
. Они будут соответствовать элементам, которые были ошибочными, передалиundefined
ихcallback
, находились в процессе выполнения, когда произошла ошибкаerror
или не были запущены. Подходreflect
вероятно, является более безопасным вариантом, посколькуundefined
может быть допустимым результатом вызоваiteratee
.