面试中的try ...catch

发布于:2024-04-28 ⋅ 阅读:(17) ⋅ 点赞:(0)

谈到 try...catch,相信大家都感觉非常熟悉,因为它通常用于捕获代码块中的错误,开发中经常使用它。

然而,由于知识不足,在一次面试中我对一个简单的概念踩了坑:try...catch 只能捕获同步代码块中的错误。

问题是:以下代码有什么问题?如果有问题,应该如何更正?

try {
  setTimeout(() => {
    throw new Error('err')
  }, 200);
} catch (err) {
  console.log(err);
}

try {
  Promise.resolve().then(() => {
    throw new Error('err')
  })
} catch (err) {
  console.log(err);
}

基本上,我不知道发生了什么,因为我的先前知识并没有包括这一点:try...catch 无法捕获异步代码中的错误,因为它本身是一个同步块。所以,当我看到这个问题时,我感到困惑。

我们通常不是这样写代码的吗,使用 try...catch 来捕获错误?所以,我只是回答说我不知道,认为没有错误…… 面试官无奈地看着我,建议我之后查一下,然后就这样了。

我迅速进行了研究,发现 try...catch 无法捕获异步代码中的错误。

在 JavaScript 中,setTimeout 是一个异步函数,它的回调函数会在指定的延迟之后被放入事件队列中,并且只有在当前执行栈被清空后才会执行。

因此,当 setTimeout 回调执行并抛出错误时,try...catch 已经执行完毕,无法捕获来自异步回调的错误。

正确的做法是直接在异步操作中处理错误,例如使用回调函数、Promises,或者结合 try...catch 使用 async/await

new Promise((resolve, reject) => {
  setTimeout(() => {
    try {
      throw new Error('err');
    } catch (err) {
      reject(err);
    }
  }, 200);
})
  .then(() => {
    // Logic for when things go as expected
  })
  .catch((err) => {
    console.log(err); // Error caught here
  });

对于第二个示例,尝试使用 try...catch 来捕获 Promise 链中抛出的错误也是无效的,因为 try...catch 无法捕获 Promise 链中的异步错误。

Promise 对象表示异步操作的最终完成(或失败)及其结果值。Promise 的状态可能是以下之一:

  • 待定(等待状态):初始状态,既不完成也不失败。
  • 已完成(完成状态):表示操作成功完成。
  • 已拒绝(失败状态):表示操作失败。

在 Promise 中抛出错误(例如,通过 throw 语句)会导致 Promise 被拒绝(或失败)。要正确处理这个错误,你需要在 Promise 链中使用 .catch 方法或在异步函数中使用 try...catch

// Method one
Promise.resolve()
  .then(() => {
    throw new Error('err');
  })
  .catch((err) => {
    console.log(err); // Error caught here
  });

// Method two
async function handleError() {
  try {
    await Promise.resolve().then(() => {
      throw new Error('err');
    });
  } catch (err) {
    console.log(err); // Error caught here
  }
}

handleError();

总结

从以上案例中,我们应该了解到 try...catch 结构无法捕获异步代码中的错误。

在处理异步操作时,采用适当的错误处理机制至关重要,例如在 Promise 中使用 .catch 方法或在 async/await 结构中使用 try...catch 来处理错误。

这种方法不仅可以有效地捕获和处理异步操作中可能发生的异常,还可以确保代码的健壮性和可维护性。

此外,在日常开发工作中,我们应该有意识地深入理解 JavaScript 运行时机制和异步编程模型,这对我们个人的职业成长起着重要作用。


网站公告

今日签到

点亮在社区的每一天
去签到