广州有专做网站,网站ui设计标准,线上运营推广,html网站制作教程宏任务#xff1a;
是指#xff0c;需要排队等待 JavaScript 引擎空闲时才能执行的任务#xff0c;
常见的宏任务包括 setTimeout、setInterval、setImmediate#xff08;Node.js 独有#xff09;、requestAnimationFrame、I/O 操作、XMLHttpRequest、DOM事件等
微任务…宏任务
是指需要排队等待 JavaScript 引擎空闲时才能执行的任务
常见的宏任务包括 setTimeout、setInterval、setImmediateNode.js 独有、requestAnimationFrame、I/O 操作、XMLHttpRequest、DOM事件等
微任务
是指在当前任务执行结束后立即执行的任务它可以看作是在当前任务的“尾巴”添加的任务
常见的微任务包括 Promise回调函数、process.nextTick、Object.observe已废弃、MutationObserver
说一下
JavaScript引擎会先执行当前任务中的所有微任务然后再执行宏任务队列中的第一个任务这个过程会不断重复直到宏任务队列中的任务被全部执行完毕。
宏任务、微任务都属于异步任务
宏任务包括 setTimeout、setInterval、I/O 等操作
微任务包括 promise的then、resolve、reject 等
首先执行同步代码遇到异步任务如果是宏任务就放入宏任务队列微任务就放到微任务队列
当同步代码执行完毕就会执行微任务队列直到微任务队列清空
然后从宏任务对列调用宏任务到主线程执行就这样不断循环直到所有任务执行完毕 JavaScript之所以要区分微任务、宏任务是因为微任务和宏任务的执行顺序不同这对Web开发中一些异步操作的实现有重要的影响
在JavaScript中微任务会优先于宏任务执行 这意味着在当前任务执行结束后所有微任务都会被立即执行而宏任务只有在所有微任务执行完毕后才会执行 这种执行顺序保证了微任务的优先级可以避免一些问题的出现。
1、 比如处理 Promise对象时可能会出现的竞态条件
举个例子当我们使用Promise对象时它会返回一个Promise实例并将回调函数放入微任务队列中
当 Promise的状态发生改变时它会立即执行微任务队列中的回调函数而不是等待当前任务结束后再执行
这种特性可以保证 Promise回调函数的执行顺序避免出现竞态条件从而使代码更加可靠。
补充举例解释一下 假设有两个Promise对象P1、P2 它们的状态都发生了改变但是P1的回调函数在微任务队列中先于P2的回调函数执行 这种情况下即使P2的状态改变发生在P1之前P2的回调函数也会等待P1的回调函数执行完毕后再执行 这样可以避免多个回调函数同时执行而产生的竞态条件。
如果当前任务执行一半了Promise状态发生改变了会停下当前任务去执行微任务队列中Promise的回调函数吗 不会的 即使当前任务执行了一半如果Promise状态发生改变也会立即执行微任务队列中的回调函数 但是不会停下当前任务的执行。当前任务的执行会继续完成然后才会回到微任务队列中执行其他的回调函数 因此即使Promise状态发生改变也不会直接打断当前任务的执行。
2、 另一方面宏任务的执行是在当前任务结束后才会执行的这意味着可以将一些耗时的操作放入宏任务队列中从而避免阻塞当前任务的执行
比如我们可以将一些需要等待一段时间才能执行的代码放入 setTimeout 的回调函数中
这样可以使页面在执行这些代码的同时仍然保持响应提高用户体验。
因此JavaScript 之所以要区分微任务和宏任务是为了保证异步操作的正确性和性能。 JS中微任务和宏任务执行顺序
1、首先执行当前代码同步任务直到遇到第一个宏任务或微任务
2、如果遇到微任务则将它添加到微任务队列中继续执行同步任务
3、如果遇到宏任务则将它添加到宏任务队列中继续执行同步任务
4、当前任务执行完毕后JavaScript引擎会先执行所有微任务队列中的任务直到微任务队列为空
5、然后执行宏任务队列中的第一个任务直到宏任务队列为空
重复步骤4、步骤5直到所有任务都被执行完毕。
需要注意的是微任务比宏任务优先级要高因此在同一个任务中如果既有微任务又有宏任务那么微任务会先执行完毕
而在不同的任务中宏任务的执行优先级要高于微任务因此在一个宏任务执行完毕后它才会执行下一个宏任务和微任务队列中的任。
举个例子
假设当前代码中有一个 setTimeout宏任务 和一个 Promise微任务它们分别对应一个宏任务和一个微任务。那么执行顺序如下
1、执行当前代码将 setTimeout 和 Promise 添加到宏任务和微任务队列中
2、当前任务执行完毕JavaScript引擎先执行微任务队列中的 Promise回调函数
3、微任务队列为空后再执行宏任务队列中的 setTimeout回调函数。
需要注意的是在一些特殊情况下微任务和宏任务的执行顺序可能会发生变化比如在使用 MutationObserver 监听 DOM 变化时 它会被视为一个微任务但是它的执行顺序可能会比其他微任务更靠后。因此需要根据具体情况来理解和处理微任务和宏任务的执行顺序。 看下面几个案例
1、微任务Promise回调函数宏任务setTimeout回调函数
console.log(start)setTimeout(() console.log(setTimeout), 0)Promise.resolve().then(() console.log(Promise))console.log(end)// start、end、Promise、setTimeout首先输出 start然后通过 setTimeout 方法注册了一个回调函数它会被添加到宏任务队列中
接着创建了一个 Promise实例并且通过 then方法注册了一个回调函数在 Promise对象的状态改变时会执行这个回调函数
接着输出 end
因为 Promise回调函数是微任务所以它会被添加到微任务队列中等待执行
等到主线程的同步任务执行完毕后JavaScript引擎会先执行微任务队列中的任务输出 Promise然后执行宏任务队列中的任务输出 setTimeout。 2、微任务process.nextTick回调函数宏任务setImmediate 回调函数
console.log(start)setImmediate(() console.log(setImmediate))process.nextTick(() console.log(process.nextTick))console.log(end)// start、end、process.nextTick、setImmediate在Node.js环境中process.nextTick回调函数是排在微任务队列最前面的优先级比 Promise回调函数还要高 而 setImmediate回调函数是排在宏任务队列最后面的。
所以以上代码会先输出 start然后输出 end 等到主线程的同步任务执行完毕后JavaScript引擎会先执行微任务队列中的任务输出 process.nextTick然后执行宏任务队列中的任务输出 setImmediate。 3、微任务Promise回调函数宏任务requestAnimationFrame回调函数
console.log(start)requestAnimationFrame(() console.log(requestAnimationFrame))Promise.resolve().then(() console.log(Promise))console.log(end)// start、end、Promise、requestAnimationFrame首先输出 start然后通过 requestAnimationFrame方法注册了一个回调函数它会被添加到宏任务队列中
接着创建了一个 Promise实例并且通过 then方法注册了一个回调函数在 Promise对象的状态改变时会执行这个回调函数
接着输出 end
因为 Promise回调函数是微任务所以它会被添加到微任务队列中等待执行
等到主线程的同步任务执行完毕后JavaScript引擎会先执行微任务队列中的任务输出 Promise然后执行宏任务队列中的任务输出 requestAnimationFrame。 4、微任务Promise回调函数宏任务XMLHttpRequest
console.log(start)// 创建 XMLHttpRequest对象并设置 onload回调函数。这个函数会在 HTTP请求成功完成后被调用。
const xhr new XMLHttpRequest()
xhr.onload () console.log(XMLHttpRequest)
xhr.open(GET, someurl)
xhr.send()Promise.resolve().then(() console.log(Promise))console.log(end)// start、end、Promise、XMLHttpRequest首先输出 start然后创建了一个 XMLHttpRequest对象并且通过 open方法 和 send方法发送了一个 GET请求
接着通过 onload方法注册了一个回调函数在请求成功后会执行这个回调函数
接着创建了一个 Promise实例并且通过 then方法注册了一个回调函数在 Promise对象的状态改变时会执行这个回调函数
接着输出 end
因为 Promise回调函数是微任务所以它会被添加到微任务队列中等待执行
等到主线程的同步任务执行完毕后JavaScript引擎会先执行微任务队列中的任务输出 Promise
然后等待 XMLHttpRequest对象的回调函数执行
当请求成功后JavaScript引擎会执行宏任务队列中的任务输出 XMLHttpRequest。
请注意这个执行顺序取决于网络请求的速度和主线程的同步任务执行速度。如果网络请求速度较慢或者主线程的同步任务执行速度较慢那么 Promise 和 XMLHttpRequest 的执行顺序可能会稍有不同。