【问题标题】:How to structure try/catch with async/await? [duplicate]如何使用 async/await 构建 try/catch? [复制]
【发布时间】:2019-09-30 20:14:09
【问题描述】:

我有以下代码,简化以省略不必要的代码:

try {
  const response = await axios.put(url, {});
  if ( response.status === 200 ) {
    MicroService.action(data);
  }
} catch ( error ) {
  // user is not signed in, so send to create-account/sign-in
  if (error.status === 401) {
    MicroService.otherAction(data);
  } else {
    console.error(`The server returned an unexpected ${error.status} error upon attempting to hit ${url}`);
  }
}

问题在于catch 子句还捕获了第四行MicroService.action(data) 中发生的任何错误。我只是想在第 2 行的 axios 调用中捕获一个错误,不应消除其他错误。

但是如果我将MicroService.action(data) 移动到catch 之后,那么即使try 失败也会发生,这是错误的。只有当try 成功时才会发生。

我可以在try 子句中设置一个变量,例如if (response.status === 200) let success = true;,然后在 catch 子句之后检查该变量。但是除了最简单的情况之外,这对于任何事情都感觉混乱和不雅。

有更好的方法吗?

【问题讨论】:

  • 你有没有试过在 catch 之后放置一个finally 块?这样它将在您的 axios 调用完成后执行。但是,您必须将您的 response 变量声明为 let 并将其移到您的尝试之外。 MDN Try/Catch 在查看更多文档后,它确实说无论是否有异常它都会执行。所以这并不能解决我认为的问题。 您可以尝试 promsify 调用 Microservice.action(data),并在 try 块中捕获它。
  • @EvanBechtol 也可以在try 中将其声明为var
  • 我认为既然 OP 似乎在使用 ES6 语法,var 会破坏样式一致性
  • 还有你的主题How to structure try/catch with async/await?,如果你不使用async/wait,你会这样做,而axios.put是一个同步请求。
  • @PatrickRoberts 当我读到这个问题时,它似乎根本没有针对 axios。当我阅读您的答案时,我发现 axios-specific 解决方案是这种情况下的最佳方法(+1),但问题本身仍然是(非常好的)重复。

标签: javascript ecmascript-6 async-await


【解决方案1】:

通过覆盖validateStatus 回调来避免vexing exceptions。如果401 状态码是预期结果,则将其视为一个并允许其他意外状态码正常抛出:

const response = await axios.put(url, {}, {
  validateStatus (status) {
    return [200, 401].includes(status);
  }
});

switch (response.status) {
case 200:
  MicroService.action(data);
  break;
case 401:
  MicroService.otherAction(data);
  break;
}

如果您不希望任何状态码引发错误,则在switch 语句中添加default 大小写:

const response = await axios.put(url, {}, {
  validateStatus () {
    return true;
  }
});

switch (response.status) {
case 200:
  MicroService.action(data);
  break;
case 401:
  MicroService.otherAction(data);
  break;
default:
  console.error(`The server returned an unexpected ${response.status} error upon attempting to hit ${url}`);
  break;
}

【讨论】:

    【解决方案2】:

    我能想到两个选择:

    1。 如果此代码在函数内部,您可以将 MicroService.action(data) 移动到 try/catch 之后,并将 return 放在 catch 中(如果适用于函数)。

    2。 then调用axios的语法:

    axios.put(url, {}).then((response) => {
      if (response.status === 200) {
        MicroService.action(data);
      }
    }).catch((error) => {
      if (error.status === 401) {
        MicroService.otherAction(data);
      } else {
        console.error(`The server returned an unexpected ${error.status} error upon attempting to hit ${url}`);
      }
    });
    

    【讨论】:

    • 尽量避免 then/catch 语法,故意尝试使用 es6 await 语法。
    • @temporary_user_name await 是 ES2017,而不是 ES2015。
    猜你喜欢
    • 2019-03-14
    • 1970-01-01
    • 2021-08-28
    • 2017-11-23
    • 2020-01-02
    • 2018-06-21
    相关资源
    最近更新 更多