宏任务: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务: process.nextTick(Nodejs), Promises, Object.observe, MutationObserver;
setTimeout(()=>{
console.log("setTimeout1");
Promise.resolve().then(data => {
console.log(222);
});
});
setTimeout(()=>{
console.log("setTimeout2");
});
Promise.resolve().then(data=>{
console.log(111);
});
//运行结果如下
111
setTimeout1
222
setTimeout2/*每一个主体代码执行 先执行宏任务 宏任务包括 setTimeOut会产生任务队列 不会立即执行,继续向下运行,直到最后一个函数,如果遇到新的宏任务,又添任务队列后方添加任务,
当主体代码执行完毕 ,把外部位promise等微任务如执行完毕,再从上向下执行宏任务,如果队列中的宏任务执行中也有任务队列,再次循环,宏任务完成后,执行微任务。
*/
【js 事件循环 Event Loop】1.主线程上没有需要执行的代码
2.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
3.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
4.首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 '111'。
此时microtask队列为空,进入下一个事件循环
5.检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 'setTimeout1',检查microtask 队列,发现队列不为空,执行promise的then回调,输出'222',microtask队列为空,进入下一个事件循环。
6.检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出'setTimeout2'。
例子 2:
console.log('script start');
setTimeout(function () {
console.log('setTimeout---0');
}, 0);
setTimeout(function () {
console.log('setTimeout---200');
setTimeout(function () {
console.log('inner-setTimeout---0');
});
Promise.resolve().then(function () {
console.log('promise5');
});
}, 200);
Promise.resolve().then(function () {
console.log('promise1');
}).then(function () {
console.log('promise2');
});
Promise.resolve().then(function () {
console.log('promise3');
});
console.log('script end');
运行结果为:
script start
script end
promise1
promise3
promise2
setTimeout---0
setTimeout---200
promise5
inner-setTimeout---0
1.首先顺序执行完主进程上的同步任务,第一句和最后一句的console.log
2.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
3.接着遇到setTimeout 200,它的作用是在 200ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
4.同步任务执行完之后,首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 'promise1',然后执行第二个promise的then回调,输出'promise3',由于第一个promise的.then()的返回依然是promise,所以第二个.then()会放到microtask队列继续执行,输出 'promise2';
5.此时microtask队列为空,进入下一个事件循环, 检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 'setTimeout---0',检查microtask 队列,队列为空,进入下一次事件循环.
6.检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出'setTimeout---200'.
接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中,检查微任务队列,即 microtask 队列,发现此队列不为空,执行promise的then回调,输出'promise5'。
7.此时microtask队列为空,进入下一个事件循环,检查宏任务队列,发现有 setTimeout 的回调函数,立即执行回调函数输出,输出'inner-setTimeout---0'。代码执行结束
为什么会需要event-loop? 因为 JavaScript 是单线程的。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环(event loops
推荐阅读
- Leetcode994腐烂的橘子(广度搜索法)
- 达内培训期间所学的知识|CGB2111开班第二十八天
- javascript|HTML之body标签中的相关标签
- 数据可视化|基于ECharts数据可视化案例--世界疫情实时展示
- 前端开发|数据可视化大屏-Vue项目
- chrome|Chrome速度无人能敌(Safari也甘拜下风)
- Leetcode542(矩阵(广度遍历解法))
- 17个实用的JavaScript数组和对象的方法
- js循环