Skip to content

使用async/await请务必添加try/catch

最早前端接口请求调用比较费劲,我想大家从初学者的时候都使用过"回调地狱"。

js
queryData(url, () => {
    getData(url, () => {
        fetchData(url, () => {
            loadData(url, () => {
                ...
            })
        })
    })
})

尤其是在Jquery时期这种代码非常的多,但是大家也没有什么太好的办法,毕竟这种连续的请求就是需要如此。

后来进入到 Promise 以后,可以使用连续的 then() 方法来进行处理,结构上显得优化了很多。

js
getData(url).then()
    .then(() => getData(url))
    ...

到现在直接使用 async/await,从结构上看显得更加的优雅了。

async/await 是 Js中用于处理异步操作的一种语法糖。它建立在 Promise 的基础之上,旨在让异步代码的编写和阅读体验更像同步代码。

async/await工作流程
  • 函数调用:当你调用一个 async 函数时,它立即返回一个 Pending 状态的 Promise
  • 执行函数体:async 函数的执行体开始运行。
  • 遇到 await:当执行到 await promiseExpression 时,判断返回的 Promise 状态,如果是 fulfilled 则继续执行,如果是 pending 则暂停执行,并等待 Promise 状态改变。

但是,为什么在async/await中一定要添加try/catch呢?

先打个比方:你在家点了一份外卖(这就像一个异步操作,比如请求服务器数据):

javascript
async function 点外卖() {
  const 外卖 = await 叫外卖(); // 等待外卖送达
  console.log("收到外卖啦:", 外卖);
}

这个过程看起来很顺利,但现实是:

  • 外卖小哥可能迷路了 🚴
  • 餐厅可能做不出来这道菜 🍝
  • 支付可能失败 💳
  • 快递可能被偷了 🚨

这些就是“异常情况”,也就是程序里的 错误(Error)或拒绝(Rejected)的 Promise

如果程序遇到错误,但你没有处理它,那么程序崩溃!

就像你点了外卖,结果没人告诉你失败了,你一直饿着等,也不知道怎么回事。

await 的本质是:

“我在这里等一下,等前面那个异步任务(Promise)完成。如果它成功了,我就拿到结果继续往下走;如果它失败了……”

⚠️ 重点来了:如果 await 后面的 Promise 被 reject(失败),JavaScript 会把这个错误当作一个“异常”抛出来,就像你写代码时手动 throw new Error() 一样。

所以正确的做法是:用 try/catch 抓住错误

javascript
async function getData() {
  try {
    const response = await fetch('/api/user');
    const user = await response.json();
    console.log("用户信息:", user);
  } catch (error) {
    // 💡 错误被捕获了!你可以在这里处理它
    console.error("哎呀,出问题了:", error.message);
    alert("加载失败,请检查网络");
  }
}

现在就像这样:

  • 你点了外卖 🍔
  • 结果餐厅说“卖完了”
  • 你立刻收到通知:“抱歉,点不了”
  • 你不会傻等,而是可以选择“换一家”或“改吃泡面”

这就是 try/catch 的作用:主动处理失败的情况,其实也就是咱们平时说的比较玄乎的防御性编程

结语

虽然try/catch非常好用但是仍需要注意:

  • try/catch 只能捕获 try 块内的 await 错误。
  • 如果你在 async 函数里 throw 错误,也会被 catch 捕获。
  • 即使用了 try/catchasync 函数本身还是返回 Promise,推荐你也可以使用.then().catch()