js事件循环机制(event loop)
栏目: JavaScript · 发布时间: 5年前
内容简介:之前在做前端的时候,可能注重的东西更偏向于业务层面的东西,切图、实现交互、调用接口等一系列比较浅的技术层,随着前端技术的不断发展,只掌握这些知识是不够的,要学会去了解如何从一个网址,渲染出来一个页面,在到后来可以让你看到你想看到的东西,并去操作它,了解浏览器底层的一些渲染机制,是作为一个优秀的前端必不可少的,这篇文章讲解的就是有关js单线程是如何执行的一篇文章,如有不足之处,请指出,我会及时作出改正。event loop在我们的日常工作当中,涉及到的地方有很多,只是大家可能不知道这个东西,就是event l
之前在做前端的时候,可能注重的东西更偏向于业务层面的东西,切图、实现交互、调用接口等一系列比较浅的技术层,随着前端技术的不断发展,只掌握这些知识是不够的,要学会去了解如何从一个网址,渲染出来一个页面,在到后来可以让你看到你想看到的东西,并去操作它,了解浏览器底层的一些渲染机制,是作为一个优秀的前端必不可少的,这篇文章讲解的就是有关js单线程是如何执行的一篇文章,如有不足之处,请指出,我会及时作出改正。
event loop在我们的日常工作当中,涉及到的地方有很多,只是大家可能不知道这个东西,就是event loop机制导致的这种渲染方式,举个:chestnut::
console.log(1) setTimeout(()=>{ console.log(3) },1) console.log(2) 复制代码
显而易见,这个结果就是:1、2、3
不管setTimeout放在当前作用域的什么位置,结果都是1、2、3,为什么,这就是event loop事件循环机制。
大家都知道,js是单线程的,如果对多进程和多线程不是特别了解,可以参考这两篇文章:
通过这两篇文章你了解什么是多进程多线程以后,可能看起来这里会好很多。
上面的例子,其实还涉及到了一个问题,就是我setTimeout设置的时间是1ms,这里要注意:
w3c在HTML标准中规定,要求setTimeout时间低于4ms的都按4ms来算
这里还要注意一点,就是有些时候,为什么一些大神用js做一些类似于动画操作的时候,喜欢用setTimeout,而不是用setInterval呢,因为setTimeout是在这个时间后,把当前的方法推到任务队列里,而setInterval是强行把当前的方法添加到任务队列里,这样可能会对当前页面的用户体验很不好,可能会出现效果卡顿的情况,所以这里还要注意一点:
setTimeout是延迟执行,但是不是延迟的时间后立即执行的
其实,event loop它最主要是分三部分:主线程、宏队列(macrotask)、微队列(microtask)
js的任务队列分为同步任务和异步任务,所有的同步任务都是在主线程里执行的,异步任务可能会在macrotask或者microtask里面
主线程
主线程就是简单点的理解,就是访问到的script标签里面包含的内容,或者是直接访问某一个js文件的时候,里面的可以在当前作用域 直接执行 的所有内容(执行的方法,new出来的对象等),都是在主线程里面做的,添加到任务队列里面的就不算了。还是老样子,举个:chestnut::
//index.html <html> <head></head> <body> <script src="index.js"></script> <script> console.log(1) setTimeout(() => { console.log(3) },1) </script> </body> </html> //index.js console.log(2) setTimeout(() => { console.log(4) },1) 复制代码
结果1和2都是在主线程里面执行的,3和4被扔到了任务队列里面。
宏队列(macrotask)
setTimeout、setInterval、setImmediate、I/O、UI rendering
微队列(microtask)
promise.then、process.nextTick、Object.observe(已废弃)
先上代码
console.log(1) process.nextTick(() => { console.log(8) setTimeout(() => { console.log(9) }) }) setTimeout(() => { console.log(2) new Promise(() => { console.log(11) }) }) requestIdleCallback(() => { console.log(7) }) let promise = new Promise((resolve,reject) => { setTimeout(() => { console.log(10) }) resolve() console.log(4) }) fn() console.log(3) promise.then(() => { console.log(12) }) function fn(){ console.log(6) } 复制代码
结果是1、4、6、3、12、8、2、11、10、9、7
这个写法可以囊括80%以上的event loop循环机制的场景了,下面开始梳理具体的运行机制。
js是从上到下执行的,所以上来先打印的是 1 ,继续往下走;
遇见了process.nextTick,因为它属于微队列(microtask),并且当前主线程的代码还没有执行完毕,所以它被展示扔到了微队列里,暂时不打印;
这个时候又遇到了setTimeout,setTimeout是属于宏队列(macrotask);
requestIdleCallback,这里也是不立即执行的,它也不属于任何队列,这里不做详细解释;
promise在实例化的时候,这里的setTimeout继续被丢到了宏队列(macrotask)中,并执行了成功的方法,在有promise.then的调用的时候就会去出发,但这里不做打印,接着发现了console,这里直接打印 4 ;
fn函数直接调用,直接打印 6 ;
console,直接打印 3 ;
promise.then因为它属于微队列,但是它在promise实例化的时候被调用了,所以它会在微队列的最前面执行;
到这里主线程里面就没有任何可以执行到东西了,下面开始走微队列(microtask):
由于promise.then被提前调用了,所以它会先执行,打印 12 ;
微队列(microtask)里面还有一个,就是上面的process.nextTick,执行它,打印 8 ,这个时候发现它有一个setTimeout,放到宏队列(macrotask);
到这里微队列就走完了,下面开始走宏队列(macrotask):
最外面的setTimeout在一开始的时候被放了进去,所以先执行它,打印 2 ,发现它里面有promise被实例化,直接执行,打印 11 ;
下一个要走的就是promise里面的setTimeout,打印 10 ;
还剩最后一个setTimeout,就是process.nextTick里面的,打印 9 ;
到这里主线程、宏队列(macrotask)、微队列(microtask)就全都跑完了,在全部跑完的时候,requestIdleCallback才会执行,打印 7 ;
requesIdleCallback会在当前浏览器空闲时期去依次执行,在整个过程当中你可能添加了多个requestIdleCallback,但是都不会执行,只会在空闲时期,去依次根据调用的顺序就执行。
console.log(1) process.nextTick(() => { console.log(8) setTimeout(() => { console.log(9) requestIdleCallback(() => { console.log(13) }) }) }) setTimeout(() => { console.log(2) new Promise(() => { console.log(11) }) }) requestIdleCallback(() => { console.log(7) }) let promise = new Promise((resolve,reject) => { setTimeout(() => { console.log(10) }) resolve() console.log(4) requestIdleCallback(() => { console.log(14) }) }) fn() console.log(3) promise.then(() => { console.log(12) requestIdleCallback(() => { console.log(15) }) }) function fn(){ console.log(6) requestIdleCallback(() => { console.log(16) }) } 复制代码
结果是1、4、6、3、12、8、2、11、10、9、7、14、16、15、13
因为这一块不涉及到事件循环里面,但是属于一个比较例外的方法,这里只做简单讲解,不做深入研究。
总结
其实,event loop用简单点的话去解释,就是:
1、先执行主线程 2、遇到宏队列(macrotask)放到宏队列(macrotask) 3、遇到微队列(microtask)放到微队列(microtask) 4、主线程执行完毕 5、执行微队列(microtask),微队列(microtask)执行完毕 6、执行一次宏队列(macrotask)中的一个任务,执行完毕 7、执行微队列(microtask),执行完毕 8、依次循环。。。
这个过程,其实就是我们具体要说的js事件循环机制(event loop)。
结束语
这些,是我在网上看一些大神的讲解,和自己对js事件循环机制(event loop)的理解,写的一篇总结性的文章,如果当中有哪些写的不对的地方,还请大家指出,我会在最短时间内作出调整。如果觉得谢的还行,帮忙给个赞吧。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- JS事件循环机制
- JavaScript运行机制和事件循环
- JS JavaScript事件循环机制
- 深入了解nodejs的事件循环机制
- 前端中的事件循环eventloop机制
- node端事件循环机制(Part1)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PCI Express 体系结构导读
王齐 / 机械工业 / 2010-3 / 55.00元
《PCI Express 体系结构导读》讲述了与PCI及PCI Express总线相关的最为基础的内容,并介绍了一些必要的、与PCI总线相关的处理器体系结构知识,这也是《PCI Express 体系结构导读》的重点所在。深入理解处理器体系结构是理解PCI与PCI Express总线的重要基础。 读者通过对《PCI Express 体系结构导读》的学习,可超越PCI与PCI Express总线......一起来看看 《PCI Express 体系结构导读》 这本书的介绍吧!