MST

星途 面试题库

面试题:JavaScript事件循环与异步错误处理的深度剖析

深入解释JavaScript事件循环机制是如何影响异步错误处理的。例如,在微任务队列和宏任务队列中分别抛出错误,其处理流程有何不同?如果在一个递归的异步函数中出现错误,如何确保错误能够被正确捕获且不会导致内存泄漏或程序崩溃?请结合具体代码示例详细说明。
11.7万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

JavaScript事件循环机制对异步错误处理的影响

  1. 事件循环机制概述:JavaScript是单线程语言,事件循环机制负责协调执行任务。它有一个调用栈(call stack)用于执行同步任务,还有宏任务队列(macrotask queue)和微任务队列(microtask queue)。当调用栈为空时,事件循环会从宏任务队列中取出一个任务放入调用栈执行,执行完后检查微任务队列,将所有微任务依次放入调用栈执行,如此循环。
  2. 微任务队列中抛出错误:微任务通常由Promise的回调、MutationObserver等产生。当微任务抛出错误时,如果没有被try - catch块捕获,会向上冒泡到全局的unhandledrejection事件处理程序。例如:
Promise.resolve()
  .then(() => {
      throw new Error('微任务中的错误');
    })
  .catch(err => {
      console.log('捕获到微任务中的错误:', err.message);
    });
window.addEventListener('unhandledrejection', event => {
  console.log('全局捕获到未处理的微任务错误:', event.reason.message);
});

在上述代码中,如果.catch块没有捕获到错误,unhandledrejection事件会捕获到该错误。 3. 宏任务队列中抛出错误:宏任务包括setTimeoutsetIntervalI/O操作、UI渲染等。当宏任务抛出错误时,如果没有在该宏任务内部的try - catch块捕获,会向上冒泡到全局的uncaughtexception事件处理程序(在Node.js环境下)或导致页面崩溃(在浏览器环境下)。例如:

setTimeout(() => {
  throw new Error('宏任务中的错误');
}, 0);
process.on('uncaughtException', err => {
  console.log('捕获到宏任务中的错误:', err.message);
});

在Node.js环境下,uncaughtException事件可以捕获到宏任务中未处理的错误。

递归异步函数中错误处理

  1. 确保错误捕获:在递归异步函数中,为了确保错误能够被正确捕获,可以在每次递归调用时使用try - catch块。例如:
async function recursiveAsyncFunction(n) {
  if (n <= 0) {
    return;
  }
  try {
    await new Promise((resolve) => setTimeout(resolve, 100));
    if (Math.random() < 0.5) {
      throw new Error('随机错误');
    }
    console.log('执行递归步骤', n);
    await recursiveAsyncFunction(n - 1);
  } catch (err) {
    console.log('捕获到递归中的错误:', err.message);
  }
}
recursiveAsyncFunction(5);

在上述代码中,try - catch块可以捕获每次递归调用中可能抛出的错误。 2. 防止内存泄漏和程序崩溃:通过正确捕获错误并处理,避免错误向上冒泡未被处理导致程序崩溃。同时,在递归结束条件正确设置的情况下,不会导致无限递归进而引发内存泄漏。例如在上述代码中,if (n <= 0)设置了递归结束条件,确保递归不会无限进行。