前言


在 JavaScript 开发者的日常中,这样的对话时常发生:

- 👨💻 新人:"为什么页面突然白屏了?"

- 👨🔧 老人:"异步请求没做错误处理吧?"

async/await 看似优雅的语法糖背后,隐藏着一个关键问题:错误处理策略的抉择。

在 JavaScript 中使用 `async/await` 时,很多人会问: “必须使用 try/catch 吗?”

其实答案并非绝对,而是取决于你如何设计错误处理策略和代码风格。

接下来,我们将探讨 async/await 的错误处理机制、使用 try/catch 的优势,以及其他可选的错误处理方法。


 async/await 的基本原理


异步代码的进化史

// 回调地狱时代

fetchData(url1, (data1) => {

 process(data1, (result1) => {

  fetchData(url2, (data2) => {

   // 更多嵌套...

  })

 })

})

// Promise 时代

fetchData(url1)

 .then(process)

 .then(() => fetchData(url2))

 .catch(handleError)

// async/await 时代

async function workflow() {

 const data1 = await fetchData(url1)

 const result = await process(data1)

 return await fetchData(url2)

}

async/await 是基于 **Promise 的语法糖**,它使异步代码看起来**更像同步代码**,从而更易读、易写。一个 async 函数总是返回一个

Promise,你可以在该函数内部使用 await 来等待异步操作完成。


如果在异步操作中出现错误(例如网络请求失败),该错误会使 Promise 进入 rejected 状态

async function fetchData() {

 const response = await fetch("https://api.example.com/data");

 const data = await response.json();

 return data;

}


<需要看新机会的>

顺便吆喝一句,技术大厂,待遇之类的给的还可以,就是偶尔有加班(放心,加班有加班费) 

前、后端/测试,多地有空位,感兴趣的可以[试试] 个比喻,就好比**铁路信号系统**


想象 async 函数是一列高速行驶的列车:


-  await 是轨道切换器:控制代码执行流向

-  未捕获的错误如同脱轨事故:会沿着铁路网(调用栈)逆向传播

-  try/catch 是智能防护系统

  - 自动触发紧急制动(错误捕获)

  - 启动备用轨道(错误恢复逻辑)

  - 向调度中心发送警报(错误日志)

为了优雅地捕获 async/await 中出现的错误,通常我们会使用 try/catch 语句。这种方式**可以在同一个代码块中捕获抛出的错误**,使得错误处理逻辑更集中、直观。

- 代码逻辑集中,错误处理与业务逻辑紧密结合。

- 可以捕获多个 await 操作中抛出的错误。

- 适合需要在出错时进行统一处理或恢复操作的场景。


async function fetchData() {

 try {

  const response = await fetch("https://api.example.com/data");

  if (!response.ok) {

   throw new Error(`HTTP error! status: ${response.status}`);

  }

  const data = await response.json();

  return data;

 } catch (error) {

  console.error("Error fetching data:", error);

  // 根据需要,可以在此处处理错误,或者重新抛出以便上层捕获

  throw error;

 }

}


不使用 try/catch 的替代方案

虽然 try/catch 是最直观的错误处理方式,但你也可以不在 async 函数内部使用它,而是**在调用该 async 函数时捕获错误**。

在 Promise 链末尾添加 `.catch()`

async function fetchData() {

 const response = await fetch("https://api.example.com/data");

 if (!response.ok) {

  throw new Error(`HTTP error! status: ${response.status}`);

 }

 return response.json();

}

// 调用处使用 Promise.catch 捕获错误

fetchData()

 .then(data => {

  console.log("Data:", data);

 })

 .catch(error => {

  console.error("Error fetching data:", error);

 });

这种方式将错误处理逻辑移至函数调用方,适用于以下场景:

- 当多个调用者希望以不同方式处理错误时。

- 希望让 async 函数保持简洁,将错误处理交给全局统一的错误处理器(例如在 React 应用中可以使用 Error Boundary)。


将 `await` 与 `catch` 结合

async function fetchData() {

 const response = await fetch('https://api.example.com/data').catch(error => {

  console.error('Request failed:', error);

  return null; // 返回兜底值

 });

 if (!response) return;

 // 继续处理 response...

}


 全局错误监听(慎用,适合兜底)

// 浏览器端全局监听

window.addEventListener('unhandledrejection', event => {

 event.preventDefault();

 sendErrorLog({

  type: 'UNHANDLED_REJECTION',

  error: event.reason,

  stack: event.reason.stack

 });

 showErrorToast('系统异常,请联系管理员');

});

// Node.js 进程管理

process.on('unhandledRejection', (reason, promise) => {

 logger.fatal('未处理的 Promise 拒绝:', reason);

 process.exitCode = 1;

});

 错误处理策略矩阵


 决策树分析


错误处理体系

1. 基础层:80% 的异步操作使用 try/catch + 类型检查

1. 中间层:15% 的通用错误使用全局拦截 + 日志上报

1. 战略层:5% 的关键操作实现自动恢复机制


 小结

我的观点是:不强制要求,但强烈推荐

-  不强制:如果不需要处理错误,可以不使用 `try/catch`,但未捕获的 Promise 拒绝(unhandled rejection)会导致程序崩溃(在 Node.js 或现代浏览器中)。

-  推荐:90% 的场景下需要捕获错误,因此 `try/catch` 是最直接的错误处理方式。

所有我个人观点:使用 async/await 尽量使用 try/catch。好的错误处理不是消灭错误,而是让系统具备优雅降级的能力。

你的代码应该像优秀的飞行员——在遇到气流时,仍能保持平稳飞行。大家如有不同意见,还请评论区讨论,说出自己的见解。

  


———转载自作者:雨夜寻晴天 

开源硬件平台

还没有评论,抢个沙发!