异步 JavaScript 中微任务队列和回调队列有什么区别?

1. 引言

在JavaScript中异步编程是我们必须要掌握的一种编程技巧。在异步编程中,微任务队列和回调队列是我们必须要了解的两个概念。在本文中,我们将会详细探讨微任务队列和回调队列的区别,以及它们在异步编程中的作用。

2. 微任务队列

先来看一下什么是微任务队列。当Web API完成一个异步操作时,会往任务队列中添加一个microtask(微任务),它会在当前宿主任务执行完毕后尽快执行。我们可以通过Promise.then()process.nextTickMutationObserver等方式向微任务队列中添加任务。

比如,下面的代码在微任务队列中添加了两个任务:

Promise.resolve().then(() => {

console.log("first task");

});

Promise.resolve().then(() => {

console.log("second task");

});

执行以上代码,它们的输出为:

first task

second task

微任务队列是一个先进先出的队列,即使在宏任务队列被阻塞的情况下,微任务队列中的任务也能得到执行。

3. 回调队列

回调队列(Callback Queue)也称之为宏任务队列(Macrotask Queue)。在Web API执行一个异步操作(比如setTimeout()setInterval()XMLHttpRequest等)的时候,它会在被添加到回调队列中,等待执行。当前宿主任务执行完毕后,会检查回调队列中是否有任务,如果有任务则执行。

比如,下面的代码向回调队列中添加了两个任务:

setTimeout(() => {

console.log("first task");

}, 0);

setTimeout(() => {

console.log("second task");

}, 0);

执行以上代码,它们的输出为:

first task

second task

回调队列是一个先进先出的队列,只有在宏任务队列被清空后才会执行。

4. 区别与联系

4.1 区别

任务类型不同:微任务队列中包含微任务,回调队列中包含宏任务。

执行顺序不同:在一个宏任务中,微任务的执行是在当前宏任务执行结束后、还没有执行下一个宏任务之前执行;回调任务的执行要等到当前宏任务执行结束并且所有微任务执行结束之后才会执行。

触发方式不同:微任务的触发方式是由JavaScript引擎主动触发,回调任务的触发方式是由Web API触发。

清空方式不同:当微任务队列执行完毕后,会清空微任务队列;当回调队列执行完毕后,会继续等待新增宏任务加入队列。

4.2 联系

微任务队列和回调队列都是在JavaScript异步编程中扮演着重要的角色。我们可以通过它们来达到将任务插入到执行队列的目的。程序的执行顺序由任务队列中任务的排列顺序决定。它们的区别与联系让我们更好地了解JavaScript的执行暗示。

5. 总结

在JavaScript中有微任务队列和回调队列两种方式来添加异步操作。微任务队列是由JavaScript引擎主动触发,可以在当前宿主任务执行完毕后尽快执行;而回调队列则是由Web API触发,等待当前宿主任务结束后清空宏任务队列,再执行回调。微任务队列执行时机早于回调队列,执行顺序也不一致。对于前端开发者而言,了解他们的区别,可以更好地掌握JavaScript的异步编程,写出更简洁、高效的代码。