Skip to content

javascript 异常处理

Posted on:August 27, 2025 at 02:52 AM

javascript 异常包括

  1. 同步异常
  2. 异步异常
  3. Promise 异常

本文将分析各个异常的不同表现形式,以及它们在 Node.js 和浏览器环境下的处理方式。


1️⃣ 同步异常

最基本的异常就是 同步代码里抛出的错误

function foo() {
  throw new Error("同步异常");
}

try {
  foo();
} catch (err) {
  console.log("捕获到异常:", err.message);
}

特点:

  1. throw 会立即停止当前函数的执行。

  2. 异常会沿调用栈向上传递,直到被 try/catch 捕获。

  3. 如果没有捕获,JS 引擎会将其视为未捕获异常(uncaught exception)。

    • 浏览器:会在控制台打印错误,但一般不会停止整个 JS 线程。
    • Node.js:默认会终止进程(除非注册了 process.on('uncaughtException'))。

2️⃣ 异步异常 — 回调函数

在 JS 里,最早的异步机制是 回调

setTimeout(() => {
  throw new Error("异步异常");
}, 1000);

注意

try {
  setTimeout(() => {
    throw new Error("异步异常");
  }, 1000);
} catch (err) {
  console.log("捕获到吗?", err); // ❌ 捕获不到
}

总结:传统回调的异步异常,必须在回调内部处理,否则无法被外部捕获。


3️⃣ Promise 异常(ES6+)

Promise 引入了 链式异常控制

new Promise((resolve, reject) => {
  reject(new Error("Promise reject"));
})
  .then(() => console.log("成功"))
  .catch(err => console.log("捕获到异常:", err.message));

特点:

  1. reject 会被下一个 .catch() 捕获
  2. 如果没有 .catch(),Node.js 就会触发 unhandledRejection
  3. async/await 本质上就是 语法糖,它把 Promise reject 转换成了同步抛异常的风格。

3.1 async/await 和 try/catch

async function foo() {
  await Promise.reject(new Error("异步异常"));
}

foo().catch(err => console.log("捕获到异常:", err.message));
async function foo() {
  try {
    await Promise.reject(new Error("异步异常"));
  } catch (err) {
    console.log("捕获到异常:", err.message);
  }
}

4️⃣ Node.js 的异常控制流特点

Node.js 里有两个关键事件:

  1. 同步未捕获异常

    process.on("uncaughtException", err => {
      console.error("捕获到同步异常:", err);
    });
  2. Promise 未处理异常

    process.on("unhandledRejection", (reason, promise) => {
      console.error("未处理的Promise异常:", reason);
    });

5️⃣ 异常控制流的传递规则

可以总结成一张逻辑表:

异常类型是否同步捕获方式Node.js 默认行为
throw✅ 同步try/catch未捕获 → 进程终止
回调里 throw❌ 异步回调内部 try/catch未捕获 → 进程终止
Promise reject❌ 异步.catch()await + try/catch未捕获 → unhandledRejection → 进程终止
async 函数 throw❌ 异步try/catch.catch()未捕获 → unhandledRejection → 进程终止

🔑 核心结论

  1. 同步异常 → try/catch 捕获。
  2. 异步异常(Promise reject) → 必须用 .catch()await + try/catch
  3. 未处理异常 → Node.js 会终止进程,浏览器只报错。

最后再看几个特殊的例子

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error");
  }, 1000);
});

async function main() {
  try {
    await promise;
  } catch (err) {
    console.log(err);
  }
}

main();

等价于

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error");
  }, 1000);
});

function main() {
  promise.catch(err => {
    console.log(err);
  });
}

main();

下面这个例子中,try catch 并不能捕获到 promise.catch 中 throw 的 err

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error");
  }, 1000);
});

async function main() {
  try {
    promise.catch(err => {
      throw err;
    });
  } catch (error) {
    console.log(error);
  }
}

main();

下面这个例子中,main 函数延迟 2s 执行,这种情况下 try catch 也捕获不到 err

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error");
  }, 1000);
});

async function main() {
  try {
    await promise;
  } catch (error) {
    console.log(error);
  }
}

setTimeout(() => {
  main();
}, 2000);

但是如果把 2s 改为 0.5s,这种情况下就能 catch 到 err 了

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error");
  }, 1000);
});

async function main() {
  try {
    await promise;
  } catch (error) {
    console.log(error);
  }
}

setTimeout(() => {
  main();
}, 500);