在 JavaScript 中,任务分为两种类型:微任务(Microtask)和宏任务(Macrotask)。它们的执行顺序以及在事件循环(Event Loop)中的位置不同。
微任务(Microtask):
- 微任务通常由 Promise 的回调函数、MutationObserver 的回调函数、Node.js 中的 process.nextTick 等创建。
- 微任务在当前任务执行完成后立即执行,不会被加入到下一个事件循环中。
- 微任务的执行优先级高于宏任务。
宏任务(Macrotask):
- 宏任务包括整体代码块、setTimeout、setInterval、I/O 操作等。
- 宏任务会被加入到事件队列的末尾,在当前任务执行完成后执行。
- 宏任务的执行顺序在微任务之后。
下面是一个示例来说明它们之间的执行顺序:
console.log(1) const promise = new Promise((resolve, reject) => { console.log(2); setTimeout(() => { resolve(3); reject(4); },0);
}); promise.then((data) => { console.log(data);
}).catch((error)=> { console.log(error);
}); console.log(5);
输出结果
1
2
5
3
解析
- js 执行代码是从上到下执行的,遇见微任务就添加到微任务队列,遇到宏任务就添加到宏任务队列(宏任务先于微任务执行,同层级微任务先于宏任务执行)
- 首先执行 console.log(1),输出 1。
- 接着执行 new Promise,在 Promise 函数中会立即执行 console.log(2),输出 2。
- 在 Promise 函数中,使用 setTimeout 定时器注册一个回调函数延时时间为 0,该回调函数会被添加到宏任务队列中,等待下一次事件循环的执行。
- 接着执行 promise.then 和 promise.catch 方法,但是由于 Promise 还未被解决或拒绝,因此这两个方法会被添加到微任务队列中,等待 Promise 状态的改变。
- 接着执行 console.log(5),输出 5。
- 由于微任务队列中有任务需要执行,因此在本次事件循环中,会先执行微任务队列中的任务。在微任务队列中,首先执行 promise.then 方法中的回调函数,输出 3。
- 接着执行 promise.catch 方法中的回调函数,由于 Promise 已经被解决该回调函数不会被执行。
总之,事件循环中的微任务优先级高于宏任务,微任务会在当前任务执行完毕后立即执行,而宏任务则会在当前任务执行完毕后排队等待执行。
js微任务和宏任务有哪些
- 微任务:Promise 回调函数、process.nextTick、Object.observe(已废弃)、MutationObserver。
- 宏任务:setTimeout、setInterval、setImmediate(Node.js 独有)、requestAnimationFrame、I/O 操作、UI 渲染。
需要注意的是,不同的 JavaScript 引擎可能会存在一些差异,有些任务可能既可以作为微任务,也可以作为宏任务,比如在一些浏览器中,使用 MutationObserver 监听 DOM 变化时,它会被视为一个微任务,但是在一些 Node.js 版本中,它会被视为一个宏任务。 另外,需要注意的是,Promise 回调函数是微任务,但是它的内部代码可能会包含其他的异步操作,这些异步操作可能是微任务或宏任务,因此在处理 Promise 时需要考虑到它内部可能包含的其他异步操作。