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

12次阅读

共计 2429 个字符,预计需要花费 7 分钟才能阅读完成。

宏工作: 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

正文完
 0