返回

字节面试题揭秘 async/await 神奇执行序**

前端

引言

在前端开发中,异步编程早已成为重中之重。掌握异步编程技术,是进阶为资深开发者的必备技能。近日,字节跳动面试中一道关于 async/await 执行顺序的难题引发热议。本篇博文将深入剖析这道难题,带你领略 JavaScript 异步编程的奇妙世界。

面试题解析

面试题如下:

async function f1() {
  console.log('f1 start');
  await f2();
  console.log('f1 end');
}

async function f2() {
  console.log('f2 start');
  setTimeout(() => {
    console.log('f2 end');
  }, 0);
}

f1();

执行顺序分析

乍看之下,这是一道普通的执行顺序题。按照顺序执行,应该先输出 "f1 start",再输出 "f2 start",然后是 "f2 end",最后输出 "f1 end"。然而,实际执行结果却令人惊讶:

f1 start
f2 start
f1 end
f2 end

这是为什么呢?

async/await 的魔法

关键就在于 async/await 机制。async 函数内部的 await 可以使函数暂停执行,直到其等待的 Promise 被解决。在我们的例子中,f1 函数中的 await f2() 暂停了 f1 的执行,直到 f2 函数返回的 Promise 被解决。

而 f2 函数中的 setTimeout() 设置了一个延迟为 0 的计时器,这意味着它会被立即执行。但由于 setTimeout() 返回的是一个 Promise,因此 f2 函数并不会立即结束,而是处于 pending 状态。

由于 f1 函数被暂停,JavaScript 引擎继续执行后面的代码。此时,f1 函数中的 console.log('f1 end') 被执行,输出 "f1 end"。

最后,当 setTimeout() 计时器触发时,f2 函数的 Promise 被解决,f1 函数恢复执行,输出 "f2 end"。

总结

这道面试题巧妙地考查了 async/await 和 Promise 的执行机制。理解了它们之间的协作关系,才能真正掌握 JavaScript 异步编程的奥秘。

进阶思考

除了理解执行顺序,我们还可以思考一下这道题目的实际应用场景。在真实开发中,异步操作往往会涉及到多个 Promise 的组合和并发执行。如何高效地管理这些异步操作,并保证代码的正确执行,是一门需要不断探索和掌握的艺术。

结语

通过分析字节跳动面试题,我们不仅掌握了 async/await 的执行顺序,更深入了理解了 JavaScript 异步编程的精髓。作为一名技术博客创作专家,我的使命就是通过独到的视角,为读者提供有价值的技术知识和见解。希望这篇文章能为你的前端技能提升之旅添砖加瓦。