
本文深入探讨 JavaScript 事件循环中的任务队列(Task Queue)和微任务队列(Job Queue/Microtask Queue)的执行顺序。通过分析 setTimeout 和 Promise 的交互,揭示了即使微任务队列优先级更高,依赖于任务队列中任务的微任务也必须等待其依赖的任务执行完毕后才能执行。本文将通过代码示例详细解释这一过程,并提供相关注意事项,帮助开发者更好地理解 JavaScript 的异步机制。
JavaScript 是一种单线程语言,这意味着它一次只能执行一个任务。为了处理异步操作,JavaScript 使用事件循环机制。事件循环不断地检查调用栈是否为空,如果为空,则从任务队列中取出第一个任务放入调用栈中执行。
事件循环主要包含以下几个关键组成部分:
微任务队列的优先级高于任务队列。这意味着,当调用栈为空时,事件循环会首先检查微任务队列,如果微任务队列中有任务,则会优先执行微任务队列中的所有任务,直到微任务队列为空,才会去执行任务队列中的任务。
立即学习“Java免费学习笔记(深入)”;
setTimeout 的回调函数会被放入任务队列中,而 Promise.then 的回调函数会被放入微任务队列中。因此,通常情况下,Promise.then 的回调函数会比 setTimeout 的回调函数更早执行。
考虑以下代码:
setTimeout(() => {
console.log('1');
}, 0);
Promise.resolve('2').then(console.log);
console.log('3');这段代码的执行顺序如下:
因此,最终输出结果为 3 2 1。
现在,考虑以下代码:
setTimeout(() => {
console.log('1');
}, 0);
Promise.resolve(setTimeout(() => {
console.log('2');
}, 0));
console.log('3');这段代码的执行顺序有所不同。Promise.resolve 接收的是 setTimeout 的返回值(timeout ID),而不是 setTimeout 回调函数本身。这意味着 Promise.resolve 立即被解析,并将一个已经完成的 Promise 放入微任务队列。而 setTimeout 的回调函数仍然在任务队列中等待执行。
因此,这段代码的执行顺序如下:
因此,最终输出结果为 3 1 2。
关键在于,即使 Promise.then 的回调函数在微任务队列中,但它依赖于 setTimeout 的执行结果(虽然这里只是 setTimeout 的 ID,但仍然存在依赖关系)。因此,setTimeout 必须先执行,Promise.then 才能完成。
通过理解 JavaScript 事件循环的机制,我们可以更好地编写高效、可靠的异步代码。
以上就是JavaScript 事件循环:任务队列与微任务队列的执行顺序详解的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号