有没有网站是免费做店招图片的,服务器出租网站,河南睢县筑宇建设网站,深圳设计公司vi设计模板前言
在JavaScript中#xff0c;任务被分为同步任务和异步任务。
同步任务#xff1a;这些任务在主线程上顺序执行#xff0c;不会进入任务队列#xff0c;而是直接在主线程上排队等待执行。每个同步任务都会阻塞后续任务的执行#xff0c;直到它自身完成。常见的同步任…前言
在JavaScript中任务被分为同步任务和异步任务。
同步任务这些任务在主线程上顺序执行不会进入任务队列而是直接在主线程上排队等待执行。每个同步任务都会阻塞后续任务的执行直到它自身完成。常见的同步任务包括页面的初始化、DOM操作和某些计算任务。异步任务与同步任务不同异步任务不直接进入主线程执行而是被放入任务队列task queue中。只有当主线程空闲时才会从任务队列中取出任务来执行。异步任务不会阻塞主线程的执行。根据任务类型异步任务又被分为宏任务和微任务。
一、事件循环是什么
JavaScript 的事件循环Event Loop是其运行时环境如浏览器或 Node.js处理异步操作和回调的一种机制。它允许 JavaScript 在不阻塞单线程执行的情况下响应用户交互、处理网络请求、定时器回调等异步事件。
二、事件循环的基本基本概念和工作原理
1. 调用栈Call Stack
JavaScript 引擎有一个调用栈用于跟踪函数调用的顺序。当一个函数调用发生时它会被推入调用栈中。当函数执行完毕后它会被从调用栈中弹出。
2. 任务队列Task Queue
当异步操作如 setTimeout、setInterval、DOM 事件、Promise.resolve().then() 等完成时它们会生成一个任务task简单理解为任务就是回调函数并将这个任务放入相应的任务队列中等待执行。
这些任务队列包括宏任务队列macrotask queue和微任务队列microtask queue宏任务队列主要存放 script全局任务、setTimeout、setInterval、setImmediateNode.js 环境等微任务队列主要存放 Promise 的回调函数、MutationObserver浏览器环境等。
3. 事件循环
事件循环的基本顺序是
当调用栈为空时即没有正在执行的函数事件循环会查看任务队列。事件循环会率先查看微任务队列。如果微任务队列中有任务它会将任务逐个取出并执行直到微任务队列为空。然后事件循环会查看宏任务队列。如果宏任务队列中有任务它会将任务取出并执行。在执行宏任务的过程中可能会产生新的微任务这些微任务会被添加到微任务队列的末尾。当一个宏任务执行完毕后事件循环会再次查看微任务队列并执行其中的任务这个过程会一直重复直到所有的任务都被执行完毕。这个过程会持续进行形成了一个循环这就是所谓的“事件循环”。
三、宏任务和微任务
在JavaScript的事件循环中任务的执行被分为两种主要的类别宏任务MacroTask和微任务MicroTask。这两种任务类型在事件循环中的处理顺序和方式有所不同。
1. 宏任务MacroTask
宏任务通常包括
script整体代码setTimeoutsetIntervalsetImmediateNode.js 环境I/OUI渲染浏览器会在每次事件循环结束后进行UI渲染MessageChannel消息通道postMessage一些HTML5 API使用requestAnimationFrame浏览器用于定时执行动画
宏任务创建后会被放入宏任务队列中JavaScript引擎会在当前执行栈清空后从宏任务队列中取出队首任务执行。
2. 微任务MicroTask
微任务通常包括
Promise.then() 或 Promise.catch()MutationObserverHTML5的API用于监听DOM变更process.nextTickNode.js环境 与宏任务不同微任务是在当前宏任务执行完成后立即执行的。在JavaScript引擎执行完一个宏任务后它会先查看微任务队列并执行所有的微任务直到微任务队列为空。然后它会继续取出并执行下一个宏任务。这个过程会不断重复形成JavaScript的事件循环。
执行顺序 考虑以下的示例
javascript
console.log(script start); // 同步任务 setTimeout(function() { console.log(setTimeout); // 宏任务
}, 0); Promise.resolve().then(function() { console.log(promise1); // 微任务
}).then(function() { console.log(promise2); // 微任务
}); console.log(script end); // 同步任务
尽管setTimeout的延迟被设置为0但它的回调仍然会在所有的微任务之后执行。因此上述代码的输出顺序为script start
script end
promise1
promise2
setTimeout
这是因为当JavaScript引擎执行到setTimeout时它会将回调函数放入宏任务队列并继续执行后续的代码。当执行到Promise.then()时它会将回调函数放入微任务队列。在所有宏任务代码执行完毕后JavaScript引擎会先执行所有的微任务然后再从宏任务队列中取出并执行下一个宏任务。四、练习
练习一 console.log(Start); // 同步任务// 宏任务1setTimeout(() {console.log(Timeout callback); // 同步任务Promise.resolve().then(() {console.log(Promise 1); // 微任务1Promise.resolve().then(() {console.log(Promise 2); // 微任务2Promise.resolve().then(() {console.log(Promise 3); // 微任务3执行完执行下一个宏任务});});});}, 0);// 宏任务2setTimeout(() {console.log(Timeout222 callback); // 6}, 0);
练习二 // 开启一个微任务当dom修改时触发const observer new MutationObserver(function (mutationsList, observer) {console.log(mutationsList, observer)});const config { attributes: true, childList: true, subtree: true };console.log(script start); // 同步任务 1 (function () {console.log(自执行函数 ); // 同步任务 2})()// 宏任务2setTimeout(function () {Promise.resolve().then(function () {var element document.getElementById(app);observer.observe(element, config);var child document.getElementById(child);element.innerHTML p这是一段新的HTML内容。/p;console.log(promise11); // 同步任务 Promise.resolve().then(() {console.log(promise11 callback 1); // (3) 微任务 });Promise.resolve().then(() {console.log(promise11 callback 2); // (3) 微任务 });})console.log(setTimeout); // 同步任务 }, 0);// 宏任务3setTimeout(() {console.log(111);})Promise.resolve().then(function () {console.log(promise1); // 微任务1 Promise.resolve().then(() {console.log(promise1 callback 1); // 微任务1-2 });Promise.resolve().then(() {console.log(promise1 callback 2); // 微任务 1-3 });}).then(function () {console.log(promise2); // 微任务2 // 宏任务4setTimeout(() {console.log(微任务内的宏任务); // 宏任务队列4Promise.resolve().then(() {console.log(微任务2 promise callback); // 微任务队列4 });})Promise.resolve().then(() {console.log(promise2 callback 1); // 微任务2-1 });Promise.resolve().then(() {console.log(promise2 callback 2); // 微任务2-2 });})console.log(script end); // 同步任务3// 执行同步任务当遇到异步宏任务放入宏任务队列异步微任务放入微任务队列// 所以执行顺序// script start// 自执行函数// script end// promise1// promise1 callback 1// promise1 callback 2// promise2// promise2 callback 1// promise2 callback 2// ---宏任务2// setTimeout// promise11// MutationObserver// promise11 callback 1// promise11 callback 2// ---宏任务3// 111// ---宏任务4// 微任务内的宏任务// 微任务2 promise callback练习三script整体为何是宏任务
// 宏任务一
scriptconsole.log(script1) // 同步// 宏任务三setTimeout(() {console.log(setTimeout1);// 宏任务五setTimeout(() {console.log(setTimeout3);})})// 微任务Promise.resolve().then(() {console.log(promise1);})
/script// 宏任务二
scriptconsole.log(script2) // 同步// 宏任务四setTimeout(() {console.log(setTimeout2);// 宏任务六setTimeout(() {console.log(setTimeout4);})})// 微任务Promise.resolve().then(() {console.log(promise2);})
/script可以看出来script相当于setTimeOut开启宏任务列表执行完当前宏任务去执行微任务微任务执行完毕执行宏任务二以此类推所以输出结果
script1
promise1
script2
promise2
setTimeout1
setTimeout2
setTimeout3
setTimeout4