浅谈js事件循环机制
太多关于js事件循环机制的面试问题了,必须要好好看一眼小小的总结一波;于是查了很多资料,看了很多相关文档;
得出以下姿势;先来张图解释下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="root">
<h1>JS事件的循环</h1>
<h3>参考阮一峰大神:http://www.ruanyifeng.com/blog/2014/10/event-loop.html</h3>
<p>同步任务:指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;</p>
<p>异步任务:指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。</p>
<p>异步执行的运行机制如下:(同步执行也是如此,因为它可以被视为没有异步任务的异步执行。)</p>
<p>(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。</p>
<p>(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。</p>
<p>(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。</p>
<p>(4)主线程不断重复上面的第三步。只要主线程空了,就会去读取"任务队列"【事件的队列 or 消息的队列】,这就是JavaScript的运行机制。这个过程会不断重复</p>
<p>process.nextTick和setImmediate的一个重要区别:多个process.nextTick语句总是在当前"执行栈"一次执行完,多个setImmediate可能则需要多次loop才能执行完</p>
<p>
宏任务(macrotask):script(整体代码)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 环境)
微任务(microtask):Promise、 MutaionObserver、process.nextTick(Node.js环境)
</p>
<p>
同步代码:代码单线执行,发送服务器请求后,等待返回数据,会出现网页空白(阻塞网页运行) 如alert for循环
异步代码:代码发送请求后继续执行后续代码,不等待服务器返回数据(网页运行流畅)
js中常见的异步执行代码:
1.ajax请求:异步 JavaScript 和 XML
2.定时器、setTimeout:间隔一段时间才会执行,
3.事件处理函数:满足事件触发条件才会执行
</p>
</div>
<script type="text/javascript">
// 遇到【同步任务】直接执行,遇到【异步任务】分类为宏任务(macro-task)和微任务(micro-task)。
// 宏任务:整体的Script setTimeout setInterval
// 微任务:Promise process.nextTick
// 所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数
// 任务队列是一个先进先出的数据结构
// 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
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');
// 依次输出结果
// script start -> script end -> promise1 -> promise2 -> setTimeout
// for (let i = 0; i < 99999; i++) {
// console.log("我在执行 但用户不知道")
// }
// console.log("循环完毕才可以打印")
/*****************同步代码异步代码有趣的打印****************/
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i,'输出十次10')
}, 0)
}
// 立刻执行函数
for (var i = 0; i < 10; i++) {
(function(i){
setTimeout(function (){
console.log(i, '输出0-9');
},1000);
})(i);
}
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i,'输出0-9')
}, 0)
}
/*
结论:
有微则微,无微则宏 【如果微任务列表里面有任务,会执行完毕后在执行宏任务】
关于promise或者es语法参考:https://es6.ruanyifeng.com/#docs/promise
*/
</script>
</body>
</html>
鄙人才疏学浅,如有不对请指出!!!转载注明出处!!!谢谢合作!!!