js事件轮询机制

tech2022-10-16  119

Q:js为什么是单线程?

A:如果前一秒对dom元素进行了删除操作,下一秒又对该元素进行了赋值,如果是多线程的话,浏览器在解析的时候不知道该怎么处理,单线程就不会出现这种歧异。(以上观点是个人理解哈,可能底层的设计有其他的考虑),既然是单线程就会出现另一个问题,每次只能执行一个任务,如果某个任务卡住了,剩下的都无法继续执行了,所以呢,异步任务就是用来解决这种情况的。

举个例子:

js的单线程——>每条车道只允许同时通过一辆汽车(JS主线程每次只能同时执行一个任务),假如3号车突然坏掉了,又只有这一条车道,那么剩余的车只能被堵在后面(这就是同步存在的问题) 如果此时启用车道2,把3号车推到我们的应急车道—车道2,等3号车修好以后,车道1刚好没有车驶入,空闲中,再让他让他回到正常车道—车道1,就不会造成堵车了。(这就是异步操作,把异步的方法先放到事件队列中(应急车道)等待执行,等主线程中的所有任务都执行完毕后,即主线程处于空闲中的状态时,再把事件队列中的程序推入主线程开始执行)

以下代码输入结果为 2 3 1(new Promise为同步方法,放入主线程第一位,log(3)为同步,放入主线程第二位,setTimeOut为异步,放入事件队列等待执行)
setTimeout(function(){ console.log(1) }) new Promise ( function () { console.log(2) }) console.log(3) PS:异步:setTimeOut setInterval .then()回调函数,ajax请求等 同步:script标签包裹的非异步代码均为同步代码,从上到下依次执行

Q:宏任务和微任务

异步方法需要被放到事件队列中等待执行,异步方法又分为宏任务和微任务,区别就是微任务执行优先级高于宏任务

例子:3号车(宏任务)坏了以后,5号车(微任务)又坏了,两车都修好以后按照常理应该是3号车先走然后是5号车,但是5号车属于特种车辆(即微任务),所以拥有优先行使权,所以5号车先走,3号车后走。(即在事件队列中会优先执行所以的微任务,然后再去执行宏任务)

ps:宏任务:setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务:process.nextTick(nodeJS), Promises的.then()回调, Object.observe(废弃), MutationObserver

代码:输出结果 2 3 4 1
setTimeout(function(){ console.log(1) }) let temp =new Promise ( function (res,rej) { res() console.log(2) }) console.log(3) temp.then( console.log(4) )

解析:

1·setTimeOut()是异步 ——>放到事件队列(属于宏任务)
2·new Promise() 是同步——>放到主线程 第一位
3·console.log(3) 是同步——>放到主线程 第二位
4· .then()是异步放到事件队列 (属于微任务)
所以执行顺序为: 2——>3——>4——>1

总结:JS是单线程,主线程一次同时只能执行一个任务,同步方法会从上到下依次执行,如遇到异步方法会先将其推到事件队列中等待,直到主线程空闲时,才会把事件队列中等待执行的方法推到主线程依次执行,异步方法又分为宏任务和微任务两种,在事件队列开始执行时,微任务的优先级会高于宏任务,往复循环直到所有任务都执行完毕。

以上分析 如果有不对的地方欢迎各位留言指教

最新回复(0)