JS事件循环机制

JS事件循环机制

接触JS有过很长一段时间了,编程项目倒是做了有一些,但在一些基础方面还是有所欠缺
今天将深入学习、了解一下JS事件循环(Event Loop)的机制。

我们很清楚,JS是一门单线程语言。
但在这么多年的设备发展中JS仍然是单核语言,说明一定有它的道理。
在根据JS实际应用场景来看,其实原因也很简单:
js是面对浏览器的脚本语言,主要是用于操作浏览器页面Dom树。如果进行多线程的同时,当多个进程同时操作一个dom,此时就很难确定执行优先级。
因此JS作为单线程语言的现实以后应该也不会改变。

任务队列

在执行JS代码时,同步任务和异步任务将进入不同执行环境,同步的进入主线程队列执行,异步的进入异步任务队列执行。当主线程队列任务执行后,将会执行异步队列任务。
以上即为 Event Loop (事件循环)。
在异步队列中分为macro-task(宏任务)与micro-task(微任务),根据资料大概总结如下:
macro-task:js, setTimeout, setInterval, setImmediate, I/O, UI rendering
micro-task:process.nextTick, Promise
js在异步队列中将先进行宏任务,然后在执行中寻找微任务,如有则执行,否则将再次进行事件循环。
以上操作都由JS函数调用栈操作。

接下来我们由例子来引入:
demo1:

console.log("start");
setTimeout(() => console.log('1'), 300);
setTimeout(() => console.log('2'), 200);
setTimeout(() => console.log('3'), 100);
console.log("end")

以上代码下分析:
1、setTimeout为宏任务,其中的参数方法(console.log(‘1’))才将延迟执行
2、根据以上故首先输出的必不会是3
3、JS将根据setTimeout依次执行321
由此,以上代码将输出:
start
end
3
2
1

demo2:

console.log("start");
setTimeout(() => console.log('1'), 300);
setTimeout(() => console.log('2'), 200);
longTask(500);  // 模拟执行500ms的同步任务
setTimeout(() => console.log('3'), 100);
console.log("end")

以上代码分析:
1、以上代码与demo1类似,仅仅是加了一个执行500ms的同步任务
2、根据同步任务可知程序需要在longTask中停留0.5s,此时在同步任务耗时过长(此时已经耗时500=300+200了),后面代码将会阻塞,此时浏览器将会直接执行1、2的setTimeout(此时控制台无输出),而不会等待3
(以此看来,需要时间较长的方法都应该放在异步任务中执行,如果JS对于耗时较长的方法中使用异步,正常队列运行,一旦上头函数耗费时间较长,那么下面的代码将会被阻塞。)
由此,以上代码将输出:
start
end
2
1
3

demo3:

console.log("start");
for (let i = 1; i <= 3; i++) {
 setTimeout(() => {
   console.log('loop: ' + i)
 }, i * 1000);
}
console.log("end")

以上代码分析:
根据以上demo的案例我们可以很明白先输出start、end,在解析中每个循环的console.log('loop: ’ + i)加入后面的宏任务队列后依次执行。
start
end
loop: 1
loop: 2
loop: 3

demo4:

	console.log("start");
	setTimeout(() => {
	  console.log(1);
	  Promise.resolve().then(() => console.log(2))
	}, 0);
	Promise.resolve().then(() => {
	  console.log(3);
	  setTimeout(() => console.log(4), 0)
	});
	console.log("end")

以上代码分析:
我们知道promise属于微任务需要提前执行,但.then不属于全局微任务,所以以上代码仍然先执行start、end。
然后执行promise队列输出3
=> 将第一个setTimeout加入函数调用栈输出1
=>执行promise队列输出2
=>进行第二个Promise中的.then输出4
输出:
start
end
3
1
2
4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值