实用百科指南
霓虹主题四 · 更硬核的阅读氛围

Promise错误处理机制:让你的异步代码更稳

发布时间:2025-12-11 16:47:18 阅读:289 次

前端开发中,异步操作无处不在。比如从服务器拉取用户信息、提交表单数据、加载图片资源等。这些操作一旦多了,稍不注意就会让页面卡住或者直接报错崩溃。Promise 的出现让异步流程变得更可控,但很多人只用了 then,却忽略了错误处理这关键一环。

常见的 Promise 错误来源

网络请求超时、接口返回 500、JSON 解析失败,这些都可能让一个 Promise 变成 rejected 状态。如果没捕获,控制台就会打出一串红色错误,用户体验直接打折。

比如你写了个登录函数:

fetch('/api/login', { method: 'POST', body: JSON.stringify(data) })
  .then(res => res.json())
  .then(data => console.log('登录成功', data));

看着没问题,但如果网络断了,或者后端挂了,这个请求就会失败,而你没有任何提示,用户点完登录按钮像石沉大海。

用 catch 捕获错误

最直接的方式就是在 Promise 链最后加个 catch

fetch('/api/login', { method: 'POST', body: JSON.stringify(data) })
  .then(res => res.json())
  .then(data => console.log('登录成功', data))
  .catch(error => {
    console.error('请求出错了:', error);
    alert('登录失败,请检查网络或稍后再试');
  });

这样无论前面哪一步出问题,都会被 catch 捕获。适合大多数场景,简单粗暴有效。

catch 不是万能的

如果你在 then 里又抛了错,比如手动写了 throw new Error(),或者 JSON 解析出错,catch 依然能接住。但要注意,如果链式调用中间有多个 then,前面的 catch 会终止后续的 then 执行,这其实是好事,避免错误蔓延。

async/await 中的 try-catch

现在更多人喜欢用 async/await 写异步代码,看起来更像同步。这时候错误处理就得靠 try...catch 了:

async function login() {
  try {
    const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify(data) });
    const data = await res.json();
    console.log('登录成功', data);
  } catch (error) {
    console.error('登录失败:', error);
    alert('提交失败,请重试');
  }
}

这种写法逻辑更清晰,特别是连续多个异步操作时,不用一层层 then 套下去。但别忘了包 try,否则错误照样漏掉。

全局监听 unhandledrejection

即便写得再小心,也可能漏掉某些边缘情况。为了兜底,可以在全局监听未捕获的 Promise 错误:

window.addEventListener('unhandledrejection', event => {
  console.warn('未处理的 promise 错误:', event.reason);
  // 可以上报到监控系统
  // event.preventDefault(); 阻止默认警告
});

上线项目建议加上这个,能帮你发现那些被忽略的异常。

实际场景:路由跳转前检查权限

在做前端路由时,经常需要在进入某个页面前检查用户是否登录。这个判断往往依赖异步请求。比如:

router.beforeEach(async (to, from, next) => {
  if (to.meta.requiresAuth) {
    try {
      const response = await fetch('/api/user/profile');
      if (response.ok) {
        next();
      } else {
        next('/login');
      }
    } catch (error) {
      console.error('权限检查失败', error);
      next('/login'); // 出错也导向登录页
    }
  } else {
    next();
  }
});

这里如果不加 try-catch,一旦网络异常,整个路由守卫就卡住了,页面白屏。加上之后,哪怕请求失败,也能优雅降级到登录页。

错误处理不是可选项,而是保证程序健壮的必要手段。别让一个网络抖动毁了整个用户体验。