关于javascript:js-事件循环-Event-Loop

宏工作: 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等微工作如执行结束,再从上向下执行宏工作,如果队列中的宏工作执行中也有工作队列,再次循环,宏工作实现后,执行微工作。
*/

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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理