正确尝试...使用异步/等待的捕获语法

我喜欢Typescript等新功能的平坦性。但是,我不确定我是否喜欢这样一个事实,即我必须在块外部声明我正在使用的变量才能在以后使用它。这样:Async/Awaitawaittry...catch

let createdUser
try {
    createdUser = await this.User.create(userInfo)
} catch (error) {
    console.error(error)
}

console.log(createdUser)
// business
// logic
// goes
// here

如果我错了,请纠正我,但似乎最佳做法是不在正文中放置多个业务逻辑行,所以我只剩下一种选择:在块外声明,在块中分配它,然后在块中使用它。trycreatedUser

在这种情况下,最佳实践是什么?


答案 1

最佳做法似乎是不要在 try 正文中放置多个业务线逻辑

实际上我会说是的。您通常希望所有异常都使用以下值:catch

try {
    const createdUser = await this.User.create(userInfo);

    console.log(createdUser)
    // business logic goes here
} catch (error) {
    console.error(error) // from creation or business logic
}

如果您只想从承诺中捕获和处理错误,您有三种选择:

  • 在外部声明变量,并根据是否存在异常进行分支。这可以采取各种形式,例如

    • 为块中的变量赋值默认值catch
    • return早期或重新 - 来自块的异常throwcatch
    • 设置一个标志,说明块是否捕获了异常,并在某个条件下对其进行测试catchif
    • 测试变量的值是否已赋值
      let createdUser; // or use `var` inside the block
      try {
          createdUser = await this.User.create(userInfo);
      } catch (error) {
          console.error(error) // from creation
      }
      if (createdUser) { // user was successfully created
          console.log(createdUser)
          // business logic goes here
      }
    
  • 测试其类型的捕获异常,并基于此处理或重新抛出它。

      try {
          const createdUser = await this.User.create(userInfo);
          // user was successfully created
          console.log(createdUser)
          // business logic goes here
      } catch (error) {
          if (error instanceof CreationError) {
              console.error(error) // from creation
          } else {
              throw error;
          }
      }
    

    不幸的是,标准JavaScript(仍然)没有对条件异常的语法支持。

    如果您的方法没有返回被拒绝并带有足够具体错误的承诺,则可以通过在处理程序中重新抛出更合适的内容来自己执行此操作:.catch()

      try {
          const createdUser = await this.User.create(userInfo).catch(err => {
              throw new CreationError(err.message, {code: "USER_CREATE"});
          });
          …
      } …
    

    另请参阅在承诺链中处理多个捕获,了解此版本的 pre-/version。asyncawait

  • 使用两个回调而不是 /。这确实是最不丑陋的方式,我个人的建议也是因为它的简单性和正确性,不依赖于标记的错误或结果值的外观来区分承诺的实现和拒绝:trycatch

      await this.User.create(userInfo).then(createdUser => {
          // user was successfully created
          console.log(createdUser)
          // business logic goes here
      }, error => {
          console.error(error) // from creation
      });
    

    当然,它带有引入回调函数的缺点,这意味着您不能轻松地/循环或从外部函数执行早期操作。breakcontinuereturn


答案 2

另一种更简单的方法是将 .catch 附加到 promise 函数。前任:

const createdUser = await this.User.create(userInfo).catch( error => {
// handle error
})