Async: 发出错误后从 async.map() 确定未处理项目的方法

创建于 2017-07-10  ·  5评论  ·  资料来源: caolan/async

你好,

在使用 map(...) 时,有没有办法处理从 iteratee 函数发出的错误以确定尚未从提供的集合中处理多少项?

我正在使用map为一组不同的 urlsparams 等执行多个传出 HTTP 请求(使用节点request库)。通过发出这些请求中的任何一个,我可能会遇到特定错误来自我可以处理的目标服务器,但我想重新处理当前正在处理的项目,然后是map尚未接收的任何剩余项目。

我确实想知道可能在我的集合中成功处理的每个项目上设置一个标志(没有错误),然后当我感兴趣的错误被发出时,相应地处理它。 然后,也许可以从标记设置为 false 的项目中创建一个新数组,并为那些尚未处理的项目执行进一步的map ,确保我从原始地图调用原始最终回调。

不确定这是否有意义,但有没有办法实现我上面描述的内容?

question

最有用的评论

@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调用的有效结果。

所有5条评论

@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的解析。

你可以试试mapSeriesmapSeries只会运行一个请求。 即它只在当前项目完成处理时调用下一个项目(而不是一次启动所有项目)。 这意味着当发生错误并调用最终回调时,将不再运行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:

谢谢!

此页面是否有帮助?
0 / 5 - 0 等级