【问题标题】:Node async and exception handling节点异步和异常处理
【发布时间】:2016-11-17 17:48:24
【问题描述】:

我正在使用异步瀑布。当我的一个函数调用回调(错误)时,我的自定义异步回调被调用。在里面我抛出一个错误,希望它会在异步的 try 块中被捕获,但那没有发生。

try {
    async.waterfall([function1, function2], myAsyncCallback);
}
catch(err) {
    console.log("THIS CODE IS NEVER EXECUTED.");
}

var function1 = function() {
...
   //some error occurs:
   callback(new Error(errMsg), errMsg);
...
}

var function2 = function() {
...
}

function myAsyncCallback(err, result) {
    console.log("This code gets executed.");
    if (err) {
            console.log("This code gets executed too.");
            throw new Error("I want this error caught at the top around the catch around async.waterfall()");
        }
}

【问题讨论】:

  • 这就是代码格式的重要性:现在你声明myAsyncCallback inside 在你的function1 中,所以这不是真正明智的代码。您能否将其减少为minimal reproducible example,人们可以将其复制粘贴到文件并在节点中运行以查看您看到的相同内容,而不是发布保证不会因为无法运行而显示您的问题的代码?
  • @Mike,它们实际上并不在彼此的内部。更新了示例,因此希望可以清楚地说明。您应该能够删除“...”来测试它。
  • 我添加了一个答案,但可能需要更深入地了解被调用的函数。我发布了我的工作代码,看起来很像你的例子!

标签: javascript node.js


【解决方案1】:

https://runkit.com/imjosh/async-try-catch/2.0.0

var async = require('async');

try {
  async.waterfall([function1, function2], myAsyncCallback);
}
catch(err) {
  errorHandler(err);
}

function function1(callback) {
  console.log('in fn1')   
  callback(null,'fn1');   
}

function function2(fn1, callback) {
  console.log('in fn2')
  callback(null, fn1 + 'fn2');
}

function myAsyncCallback(err, result) {
    if (err) {
      console.error('There was an error: ' + err);
      return;
    }
    //an error occurs. this gets caught by the outer try block
    //var foo = outer; //oops, outer is not defined. This throws an error

    //same scenario but inside an async function
    //can't/won't be caught by the outer try block
    setTimeout(function(){ 
        try{ //need try here
          var foo = inner; //oops, inner is not defined. This throws an error
        } 
        catch(err) {
          errorHandler(err);
       }
    }, 1000);

    console.log('Result was: ' + result);
}

function errorHandler(err){ 
  //Make error handler a function that can be called from either catch
  console.log('caught error: ' + err);
}

【讨论】:

  • 异步模块回调中出现错误,我称之为myAsyncCallback。 function1 内部的错误确实会在第一个 try/catch 块中被捕获,但这不是我想要做的。
  • 我已经编辑了答案。所有的错误处理都在一个地方。 myAsyncCallback 中的异常得到处理。如果没有看到实际代码,很难看到您正在尝试做什么。
【解决方案2】:

希望它会在异步的 try 块中被捕获,但那没有发生

那是不可能的。错误将被异步创建和抛出,即在 async.waterfall 返回并离开 try 块之后很久。如果您想处理异步错误,请在myAsyncCallback 中执行(就像您已经做的那样)。永远不要在异步回调中使用throw

【讨论】:

  • 这不准确。调用async.waterfall 时创建的范围将一直保留到链终止。抛出的错误将通过调用链“冒泡”回来。我同意抛出异步回调是有问题的(因为跟踪错误是如此痛苦),但并非不可能。你能编辑这个答案吗?
  • @clay 你说的是哪个范围? OPs 代码中没有闭包,因此作用域在离开时会被销毁。或者您所说的“直到链条死亡”是什么意思?请注意,async.waterfall 不会调用在 OP 代码中引发的 myAsyncCallback - 它是异步
  • 我想我的意思是回调链。但是你是对的,如果回调被异步调用,会有不同的行为。我想我有一些学习要做!谢谢你的回答。
【解决方案3】:

为我工作。你看到有什么不同吗?如果有更多事情发生,我会更新我的答案。

这是我的输出:

[Clays-MacBook-Pro ~/Documents/workspace/scratch]:node index.js 
inside function1
This code gets executed.
This code gets executed too.
THIS CODE IS NEVER EXECUTED.
[Clays-MacBook-Pro ~/Documents/workspace/scratch]:node -v
v6.9.1
[Clays-MacBook-Pro ~/Documents/workspace/scratch]:

这段代码:

var async = require('async')
try {
    async.waterfall([function1, function2], myAsyncCallback);
}
catch(err) {
    console.log("THIS CODE IS NEVER EXECUTED.");
}

function function1(callback) {
    console.log("inside function1");
    var errMsg = "Uh oh";
   callback(new Error(errMsg), errMsg);
}

function function2(stuff2, callback) {
    console.log('inside function2');
    var errMsg = "Uh oh";
   callback(new Error(errMsg), errMsg);
}

function myAsyncCallback(err, result) {
    console.log("This code gets executed.");
    if (err) {
            console.log("This code gets executed too.");
            throw new Error("I want this error caught at the top around the catch around async.waterfall()");
        }
    console.log(result);
}

【讨论】:

  • 您的function1function2 正在同步调用它们的回调,这没有任何意义。 myAsyncCallback 应该是一个 异步 回调,否则 async.waterfall 一开始就不会被使用。
  • Bergi,我相信我们应该在每个函数中调用回调(例如,hacksparrow.com/node-js-async-programming.html)。让我们把正常的异步处理变成同步的。也许我错过了什么。
  • @Clay,你的样本对我有用。为了测试我的代码中的错误处理,我在回调中添加了 throw 语句,但我也没有创建错误并将其发送到回调:callback(err)。在我的代码中,有一个 if/else 代替了上面示例中的“...”,这导致回调调用没有被执行。
  • 在我的示例中,它被捕获的throw。将错误作为任何callback 函数的第一个参数只是一个节点约定,异步尊重并知道停止事件链。这不会出现在 catch 块中,它只处理抛出的异常。
  • Clay,正确,但如果不使用 err 参数调用“callback”,则回调方法本身中的“if (err)”(包括 throw 语句)将不会被执行。您的工作示例向我表明,尽管我上面的示例似乎表明我已经这样做了,但我并没有真正拨打电话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多