你好,
在使用 map(...) 时,有没有办法处理从 iteratee 函数发出的错误以确定尚未从提供的集合中处理多少项?
我正在使用map
为一组不同的 urlsparams 等执行多个传出 HTTP 请求(使用节点request
库)。通过发出这些请求中的任何一个,我可能会遇到特定错误来自我可以处理的目标服务器,但我想重新处理当前正在处理的项目,然后是map
尚未接收的任何剩余项目。
我确实想知道可能在我的集合中成功处理的每个项目上设置一个标志(没有错误),然后当我感兴趣的错误被发出时,相应地处理它。 然后,也许可以从标记设置为 false 的项目中创建一个新数组,并为那些尚未处理的项目执行进一步的map
,确保我从原始地图调用原始最终回调。
不确定这是否有意义,但有没有办法实现我上面描述的内容?
嗨@parky128 ,感谢您的提问!
用reflect
包装iteratee
reflect
起作用吗? reflect
总是将结果对象传递给callback
,因此即使iteratee
函数之一出错, map
也会完成。 然后你可以从map
遍历results
对象,检查哪些对象具有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
函数之一出现错误时立即调用,并带有我希望捕获的特定错误情况。
查看文档我看到我可以通过将错误传递给 iteratee 回调函数来实现这一点,但我想知道是否在 async.map 将调用的最终回调中,我是否可以使用该结果对象与原始对象进行比较收集并查看还有什么需要处理。
我只是不希望 async.map 在其中之一返回我感兴趣的错误情况时尝试处理任何其他请求。
我只是不希望 async.map 在其中之一返回我感兴趣的错误情况时尝试处理任何其他请求。
假设您的iteratee
是异步的,则async.map
将在调用最终回调时开始处理所有项目。 您可以将结果对象与集合进行比较,以查看哪些项目尚未完成处理,但这也有其问题。 例如,您必须同步执行,在调用最终回调的同一个滴答上,结果对象将更新为iteratee
的解析。
你可以试试mapSeries
。 mapSeries
只会运行一个请求。 即它只在当前项目完成处理时调用下一个项目(而不是一次启动所有项目)。 这意味着当发生错误并调用最终回调时,将不再运行iteratee
。 然后,您可以将结果与集合进行比较,以查看哪些项目尚未处理。 这仍然是一种解决方法,但它比使用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 个失败,然后我将使用错误参数调用对 iteratee 函数的回调,这是否意味着最终回调中的结果对象将只包含 async.map 4个成功的结果?
如果是这样,那么现在我将接受它仍然会拨打所有拨出电话的事实。 我可能会将我的数组拆分为较小的数组并在 mapSeries 中执行较小的 async.maps,以最大限度地减少对请求命中的目标服务器的初始命中。
@hargasinski - 我最终使用了async.reflect
方法,这对我来说效果很好,让我可以完全了解所有出现错误的项目:+1:
谢谢!
最有用的评论
嗨@parky128 ,感谢您的提问!
用
reflect
包装iteratee
reflect
起作用吗?reflect
总是将结果对象传递给callback
,因此即使iteratee
函数之一出错,map
也会完成。 然后你可以从map
遍历results
对象,检查哪些对象具有error
属性,然后相应地处理它。 您不必重新处理map
可能未提取的任何项目。否则,要回答您的问题,
map
始终返回array
。 您可以遍历该数组并检查哪些值是undefined
。 这些将对应于错误的项目,将undefined
传递给他们的callback
,在error
发生或尚未开始时正在进行中的项目。reflect
方法可能是更安全的选择,因为undefined
可能是iteratee
调用的有效结果。