Javascript执行机制(setTimeout/Promise)

1.关于javscript

    javascript是一门单线程语言,在最近的html5中提出了web-worker,但javascript是单线程这一核心仍未改变,所以一切javascript版的“多线程”都是用单线程模拟出来的,javascript就是一门单线程语言。

2.javscript的事件循环

    既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也需要一个一个的顺序执行。如果一个任务耗时过长,那么最后一个任务也必须等着。那么问题来了,如果我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一只卡到图片完全现实出来?因此聪明的程序员将任务认为两类:同步任务,异步任务

当我们打开网站时,网页渲染过程就是一大堆同步任务。执行过程用文字描述的话就是

    1.同步任务和异步任务分别进入不同的执行场所,同步的进去主线程,异步的进入enent table并注册函数。

    2.当指定的事情完成时,event table会将这个函数移步到 event queue 

    3.主线程的任务执行完毕为空,会去event queue读取对应的函数,进入主线程执行

    4.上诉过程会不断重复,也就是常说的event loop(事件循环)

    实例图:

疑问是:那怎么直到主线程的执行栈为空啊?原因是:js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去event queue那里检查是否用等待被调用的函数。

3.setTimeout  的执行方式是异步执行,用处一般为,延迟指定时间再执行移步函数。


根据前面的结论,上诉代码的打印顺序为 2,三秒后打印1 ,印证正确。

但是当遇到下面代码的时候


结果是打印1 的结果需要的时间远远超过3秒,这不符合我们想要的预期,我们想要的就是三秒后打印1 ,那么先看一下执行结果

    1.console.log(1)进入event table并注册,计时开始

    2.执行sleep函数,很慢,但是event table里的计时仍在继续

    3.3s到了 计时事件完成,console.log(1)进去event queue,但是此时主线程里的sleep还没有执行完成,console.log(1)只能继续等

    4.sleep执行完啦,console.log(1)进入主线程,从而执行

我们知道setTimeout 这个函数,是经过指定时间后,把要执行的任务加到event queue中,又因为单线程任务需要一个一个的执行,如果前面的任务需要的时间太久,此时setTimeout 的延时时间就会出现比较大的偏差。

4.setInterval

    对于执行顺序而言,setInterval会每隔指定的时间将注册的函数只如event queue,如果前面任务耗时太久,那么同样需要等待。

唯一需要注意一点的是,对于setInterval而言,我们知道不是每过指定时间就执行fn,而是每过指定时间就会有fn进入event queue。一旦setInterval的回调函数执行时间超过了延迟的时间,那么就完全看不出来有时间间隔了

5.promise

    对于promise而言,我们需要对js的执行了解的更细致一些,如下

    1.macro-task(宏任务):包括整体script代码,setInterval,setTimeout

    2.micro-task(微任务):promise ,process.nexttrick(nodejs的内容)

不同类型的任务会进入对应的event queue,比如setInterval,setTimeout会进入相同的event queue。

事件循环的顺序决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。看一下代码


分析一下上图代码,加深一下理解,(1)这段代码作为宏任务进入主线程,先遇到settimeout,那么将其回调函数分发到宏任务的event queue上,(2)接下来遇到promise,new promise立即执行,then函数分发到微任务的event queue中,(3)接下来遇到console.log()立即执行。(4)然后,整体script代码作为第一个宏任务执行结束,看看有哪些微任务,我们发现then在微任务event queue里,则执行,(5)第一轮循环事件结束,开始第二轮循环,当然是从宏任务的event queue开始,我们发现了宏任务event queue中的settimeout对应的回调函数,则立即执行。

图例如下:

6.下面一个例子练习


如果不会请看引用地址:https://juejin.im/post/59e85eebf265da430d571f89

结语:

1。javascript是一门单线程语言

2.Event Loop 是javascript的执行机制。



另一段描述

宏任务与微任务

JavaScript引擎把所有的任务分为两类,宏任务、微任务。

宏任务包括了:

1.script整体的代码

2.setTimeout、setInterval

3.I/O

4.UI渲染

5.postMessage

6.MessageChannel

7.requestAnimationFrame

8.setImmediate(nodeJs环境)

微任务包括了:

1.new promise.then()

2.MutaionObserver

3.pocess.nextTick(node.js环境下)

执行规则

我们讲了单线程的弊端,JavaScript是通过事件循环机制来解决这个弊端的,事件循环机制的执行规则。

1.所有代码作为宏任务进入主线程执行栈,开始执行。

2.执行过程中,同步代码会立即执行,宏任务进入宏任务队列,微任务进入到微任务队列。

3.当前宏任务执行完出队,读取微任务队列,有则执行,直到全部执行完毕。

4.执行浏览器ui进程渲染。

5.检查是否有webwork任务,有则执行。

6.本轮宏任务执行完成,回到第二步,继续执行,直到宏任务与微任务队列全部清空。

摘自: https://zhuanlan.zhihu.com/p/363974999

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原文在这里说明: 我通过这篇文章第一次知道JavaScript运行机制中的任务队列有宏任务和微任务之分。 文中的代...
    楠小忎阅读 271评论 0 0
  • 一.js是一门单线程的语言,js是按照语句出现的顺序执行的 二.Javascript事件循环 因为js是单线程,所...
    lmmy123阅读 345评论 0 0
  • 最近比较忙,硬是没抽出时间总结一点小知识。最近在网上看到一篇不错的文章,转一下!本文的目的就是要保证你彻底弄懂ja...
    殖民_FE阅读 286评论 1 2
  • 一、JavaScript单线程模型 JavaScript是单线程的,JavaScript只在一个线程上运行,但是浏...
    Brolly阅读 1,156评论 4 6
  • JavaScript单线程机制 JavaScript的一个语言特性(也是这门语言的核心)就是单线程。什么是单线程呢...
    October_yang阅读 530评论 0 1