【问题标题】:node.js promises: how to find out which iteration threw the exception in a .catch statement? [duplicate]node.js 承诺:如何找出哪个迭代在 .catch 语句中引发了异常? [复制]
【发布时间】:2015-07-03 10:40:40
【问题描述】:

(这不是JavaScript closure inside loops – simple practical example的重复,因为你不能选择catch函数接受哪些参数)

我不熟悉 Node.js 的异步回调特性。我试图找出 for 循环中的哪个元素引发了异常。

当前代码总是返回数组中的最后一个元素,不管是哪个元素抛出了异常。

for (i = 0; i < output.length; i++) {
    var entity = Structure.model(entity_type)[1].forge();

    /* do some stuff here which I've taken out to simplify */

    entity.save()
        .then(function(entity) {
            console.log('We have saved the entity');
            console.log(entity);
            returnObj.import_count++;
        })
        .catch(function(error) {
            console.log('There was an error: ' + error);
            console.log('value of entity: ', entity); /* THIS entity variable is wrong */
            returnObj.error = true;
            returnObj.error_count++;
            returnObj.error_items.push(error);
        })
        .finally(function() {
            returnObj.total_count++;
            if (returnObj.total_count >= output.length) {
                console.log('We have reached the end. Signing out');
                console.log(returnObj);
                return returnObj;
            } else {
                console.log('Finished processing ' + returnObj.total_count + ' of ' + output.length);
            }
        })
}

如何编写 Promise,让我可以访问引发异常的元素,以便将其存储在有问题的元素列表中?

【问题讨论】:

  • 返回最后一个元素是什么意思?
  • 我的意思是,在我遍历 30 个元素之后,它总是返回元素 30,而不是导致异常的元素(例如 15)。
  • 如果您认为不是重复的,请参考infamous loop issue。这是完全相同的问题 - 您不必选择 catchonclick 或任何回调采用的参数。
  • 非常感谢您指出这一点。恐怕我不熟悉“闭包”的词汇,也没有意识到这个问题不仅限于异步 try-catch 语句。因此,当我搜索该问题时,我没有找到您链接到的答案。有没有可能其他人会做同样的事情?

标签: javascript node.js exception callback promise


【解决方案1】:

这是因为传递给 catch 的匿名函数只能通过闭包访问entity

如果实体是原始类型,您可以通过构造一个新函数来轻松解决这个问题,该函数通过参数捕获该值(其中entity 的值将被复制构造时间)。

.catch(function(entity){ 
    return function(error) {
        console.log('There was an error: ' + error);
        console.log('value of entity: ', entity); /* THIS entity variable is wrong */
        returnObj.error = true;
        returnObj.error_count++;
        returnObj.error_items.push(error);
    };
}(entity))

(注意我是立即用()调用函数,所以catch只接收返回的函数作为参数)

如果实体是一个对象(仅通过引用传递),你可以使用相同的基本原理,但你必须创建一个这个实体的副本,这会稍微复杂一些。在这种情况下,如果您使用原语 i 编写错误处理程序(作为一种原语类型,很容易使用上述方法捕获),或者您不在循环中重用实体变量,这可能会更容易。

顺便说一句,你确定var entity = Structure.model(entity_type)[1].forge();-> 这里的1 不应该是i

【讨论】:

  • 谢谢!你的意思是我应该写 .catch(function(i) { }()) 吗?我不知道参数名称可以引用现有变量。我认为 function(variableName) 只是在新范围内实例化了一个新变量。
  • 哦 - [1] 是故意的 - 我可能也应该忽略它,因为它指的是程序中其他地方的东西。而“实体”是一个对象,这就是为什么我需要考虑您的第二个解决方案。
  • 是的,我是这个意思。如果参数名称引用现有变量,它将隐藏它,这意味着在该名称的函数内部您只能引用该参数。 (这是一个非常普遍的概念,不是特定于 javascript 的,尽管它确实经常与闭包一起使用)
  • 恐怕我无法让它为我工作。如果我将其替换为实体变量,则变量 i 将显示为未定义。
  • 替换是什么意思?将您的新代码编辑到 OP 中或显示 plunkr。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 2019-06-13
  • 1970-01-01
  • 2019-11-06
相关资源
最近更新 更多