如何在async / await情况下正确实现错误处理 [英] How to properly implement error handling in async/await case

查看:82
本文介绍了如何在async / await情况下正确实现错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用async / await ecma6标准而没有任何自定义库。

I use async/await ecma6 standard without any custom library.

我目前还没有得到如何正确捕获和抛出错误。
我有多个异步/等待函数,如果某个地方低于严重错误,我想把错误抛到顶部和所有异步函数并停止执行该函数。

I don't get at the moment how I can properly catch and throw errors. I have multiple async/await functions and if somewhere down below an critical error happens I want to throw the error to the top and of all async functions and stop execution of the function.

我试图从异步/等待函数中抛出异常并在目标函数中捕获它但在node.js中出现错误:

I tried to throw exceptions out of the async/await function and catch it in the target function but I get a error in node.js:

    this.basicAuthLogin= async function(user)
{
    "use strict";
    const login = new Login(this.host, this.url, user, user.pw);

    //getSessionID throws error
    this.sessionID = getSessionID(result.request.response);
}




(节点:13964)UnhandledPromiseRejectionWarning:未处理的承诺
rejection(拒绝ID:1):错误:getSessionID响应未定义
(节点:13964)[DEP0018]弃用警告:未处理的承诺
拒绝被弃用。将来,未处理
的承诺拒绝将使用非零退出
代码终止Node.js进程。附加调试器。

(node:13964) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: getSessionID response is undefined (node:13964) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. Debugger attached.

所以看来我不允许从异步函数中抛出异常,甚至不能在异步函数的catch块中重新抛出异常在node.js中的承诺?

So it seems I am not allowed to throw exceptions out of async functions or even rethrow it in the catch block of the promise in node.js?

那么我该怎么做呢?
我应该在异步函数中捕获错误并在promise中返回错误并重新抛出异步函数吗?

So how do I get this working? Am I supposed to catch the error in the async function and return the error in the promise and rethrow then out of the async function?

   this.basicAuthLogin= async function(user)
{
    "use strict";
    const login = new Login(this.host, this.url, user, user.pw);
   try{
    //getSessionID throws error
    this.sessionID = getSessionID(result.request.response);
   } catch(err) { return err;}
}

但是这个意味着在我的第一个异步函数的调用堆栈中,每个函数都需要异步,我必须等待承诺,即使我真的不需要它。

But this would mean that in my call stack from the first async function every function needs be async and I have to await the promise even though I don't really need it.

I希望有人能够启发我。

I hope somebody can enlighten me.

问候
Ruvi

Regards Ruvi

编辑基本调用堆栈伪代码:

Edit basic call stack pseudo code:

   async startTest[arr]{

    for (var i = 0; i < arr.length; i++)
    {
      try {
          await runStep(arr[i];
        } catch(err) { 
            console.log(err);
            break; 
        }
      }
    }

  async runStep(step)
  {
     try {
     var userIsValid = await validateUser(step.user);
     var req = buildRequest(step.request);
     var result = await sendRequest(req);
     var verify = verifyResult();
     } catch(err){ throw err;}
  }

  async validateUser(user)
  {
     //make checks
     //
     var result = await this.authenticate(parameter).catch(err => {throw err});
     userFound = true;
   }

  function authenticate(parameter) {
  //can throw async function
   basicAuthLogin(parameter).catch(err => {throw err};

   }

  function async basicAuthLogin(parameter()
  {
   try {
    //can throw  async function
      var result = await request(parameter);
      //can throw sync function
      this.sessionID = getSessionID(response);
      //can throw   sync function
      } catch(err) { throw err; }
   }


推荐答案

其中一个关于 async / await 的好处是他们启用尝试 / catch 使用异步代码。

One of the great things about async/await is that they enable try/catch to work with your asynchronous code.

你的第一个 basicAuthLogin 函数绝对正常(提供 getSessionID 同步函数; 如果不是,你错过了 await [你现在说的是] )。代码使用 basicAuthLogin 必须处理它将抛出的可能性(通过处理错误或允许它传播给其负责处理的调用者它)。所以要么:

Your first basicAuthLogin function is absolutely fine (provided getSessionID is a synchronous function; if it isn't, you're missing an await [you've now said it is]). The code using basicAuthLogin must handle the possibility it will throw (either by handling the error or allowing it to propagate to its caller, which is responsible for handling it). So either:

// In an `async` function
try {
    await this.basicAuthLogin(/*...*/);
} catch (e) {
    // Handle the fact something failed
}

// NOT in an `async` function:
this.basicAuthLogin(/*...*/)
    .catch(e => { /* Handle the fact something failed */ });

如果使用它的代码执行这两件事之一(或者让错误传播到代码那么做这两件事之一),你不会得到未处理的拒绝错误。

If the code using it does one of those two things (or lets the error propagate to code that does one of those two things), you won't get the "Unhandled rejection" error.

回应我的评论询问是否 getSessionID 是异步的,你写道:

In response to my comment asking if getSessionID was asynchronous, you wrote:


不,它不是异步它是一个抛出我想要的异常的简单函数在调用堆栈中占据5或6层,但似乎我不允许这样做。

No it is not async it is a simple function that throws an exception that I want to catch 5 or 6 floors up the call stack but it seems I am not allowed to do that.

这是一个现场直播这样做的例子(在我的例子中,我已经使 basicAuthLogin 实际上在 getSessionID ,但这并不重要):

Here's a live example of doing that (in my case, I've made basicAuthLogin actually use something asynchronous prior to getSessionID, but it doesn't really matter):

const getSessionID = () => {
  throw new Error("Failed");
};
const somethingAsync = () => new Promise(resolve => {
  setTimeout(resolve, 100);
});
const basicAuthLogin = async function(user)
{
    "use strict";
    await somethingAsync();
    /*
    const login = new Login(this.host, this.url, user, user.pw);
    */

    //getSessionID throws error
    getSessionID();
};

const wrapper1 = async () => {
  await basicAuthLogin();
};
const wrapper2 = async () => {
  await wrapper1();
};
const wrapper3 = async () => {
  await wrapper2();
};

// Top-level caller
(async () => {
  try {
    await wrapper3();
  } catch (e) {
    console.log("Caught error: " + e.message);
  }
})();

规则就像是有例外(因为这些例外):

The rule is just like it is with exceptions (because notionally these are exceptions):


  1. 要么处理它(例如,尝试 / catch ),或让它传播给调用者(通常不做任何事情),并且

  1. Either handle it (e.g., try/catch), or let it propagate to the caller (typically by not doing anything at all), and

最高级别必须处理它

该规则#2表示当您从非 async 代码转换为 async 代码时(通常位于堆栈顶部) ),你需要一个包装器。要么:

That Rule #2 means that when you transition from non-async code to async code (typically right at the top of your stack), you need a wrapper. Either:

(async () => {
  try {
    await theFirstAsyncFunction();
    await theNextAsyncFunction();
    await aThirdAsyncFunction();
  } catch (e) {
    // handle the error
  }
})();

(async () => {
  await theFirstAsyncFunction();
  await theNextAsyncFunction();
  await aThirdAsyncFunction();
})().catch(e => { /* handle the error */});

当然还是:

theFirstAsyncFunction()
.then(() => theNextAsyncFunction())
.then(() => aThirdAsyncFunction())
.catch(e => { /* handle the error */});

有一个共同点:顶级总是处理错误。

The common denominator there is: The top level always handles the error.

这篇关于如何在async / await情况下正确实现错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆