返回

剖析一道Promise面试难题,揭秘EventLoop背后玄机

前端

揭秘 Promise 变态面试题:深入剖析 EventLoop 的玄机

简介

在 JavaScript 开发世界中,Promise 已成为异步编程的基石。理解 Promise 的运作原理至关重要,而本文将通过一道变态面试题,深入剖析 Promise 和 EventLoop 的奥秘。

谜题

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1');
  resolve('promise1');
});

const promise2 = new Promise((resolve, reject) => {
  console.log('promise2');
  setTimeout(() => {
    resolve('promise2');
  }, 0);
});

promise1.then(data => {
  console.log(data);
  return promise2.then(data2 => {
    console.log(data2);
  });
});

解决方案

要解开这道谜题,我们必须分步剖析代码的执行流程:

  1. 创建 Promise: 代码创建两个 Promise 对象:promise1promise2,并立即执行其构造函数。

  2. promise1 状态改变: promise1 内部立即调用 resolve('promise1'),将状态从 pending 更改为 resolved,并传递数据 'promise1'

  3. 创建延迟任务: promise2 内部创建一个延迟任务,使用 setTimeout 在 0 毫秒后将状态更改为 resolved,并传递数据 'promise2'

  4. promise1.then promise1.then 方法创建一个新的 Promise,其状态取决于 promise1 的状态。由于 promise1 已 resolved,因此新 Promise 立即 resolved,并继续执行其 then 方法。

  5. 等待 promise2 新 Promise 的 then 方法返回一个新 Promise,其状态取决于 promise2 的状态。由于 promise2 的状态尚未 resolved,因此该 Promise 进入 pending 状态。

  6. 执行延迟任务: EventLoop 检测到 promise2 的延迟任务,并在下一个事件循环中执行它。这导致 promise2 状态更改为 resolved,触发了等待它的 Promise。

  7. 最终结果: 等待 promise2 的 Promise 现在 resolved,并执行其 then 方法,打印出数据 'promise2'

输出:

promise1
promise1
promise2

EventLoop 的作用

EventLoop 是 JavaScript 异步编程的幕后推手。它不断检查任务队列,并在队列中有新任务时立即执行它们。

在这个例子中,当 setTimeout 任务被创建时,它被放入任务队列。EventLoop 在下一个事件循环中检查队列,发现任务并执行它,从而改变了 promise2 的状态。

结论

通过解决这道变态面试题,我们深入理解了 Promise 和 EventLoop 的运作原理。掌握了这些概念对于编写高效且健壮的异步代码至关重要。

常见问题解答

  1. 为什么 promise1then 方法中的 data'promise1'

    • 因为它是在 promise1 resolved 后执行的。
  2. 为什么 promise2 的延迟任务是在 0 毫秒后执行的?

    • 这样可以确保它在下一个事件循环中执行,并且在 promise1then 方法执行完毕后执行。
  3. EventLoop 总是检查任务队列吗?

    • 是的,EventLoop 始终监视任务队列,并尽快执行新任务。
  4. 如何避免 EventLoop 阻塞?

    • 避免在事件循环中执行繁重的任务,使用 setTimeoutrequestAnimationFrame 将任务分解为较小的块。
  5. 为什么异步代码是重要的?

    • 异步代码使我们能够在不阻塞主线程的情况下执行任务,从而保持应用程序的响应能力。