ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浏览器环境下 js 引擎的事件循环机制

2020-09-25 20:00:44  阅读:168  来源: 互联网

标签:异步 浏览器 js 任务 引擎 事件 栈中 执行


1. 执行栈与事件队列

当 javascript 代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。

我们知道,当我们调用一个方法的时候,js 会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中存在着这个方法的私有作用域,上层作用域的指向,方法的参数,这个作用域中定义的变量以及这个作用域的 this 对象。而当这些方法被排队在一个单独的地方。这个地方就被称为执行栈。

当一个脚本第一次执行的时候,js 引擎会解析这段代码,并将其中的同步代码按照执行顺序加入到执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么 js 会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码执行完毕并返回结果后,js 会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。这个过程反复执行,直到执行栈中的代码全部执行完毕。

从图片中可知,一个方法执行会向执行栈中加入这个方法的执行环境,在这个执行环境中还可以调用其他方法,甚至是自己,其结果不过是在执行栈中再添加一个执行环境。这个过程是可以无限进行下去的,除非发生栈溢出,即超过了所能使用内存的最大值。

以上的过程说的都是同步代码的执行。那么当一个异步代码(如发送 Ajax 请求数据)执行后会如何呢?前文提过,js 的另一大特点是非阻塞,实现这一点的关键是 ——事件队列(Task Queue)。

js 引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js 会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。被放入事件队列不会立即执行其回调,而是等待当前执行栈中的所有任务都执行完毕,主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中去除排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...,如此反复,这样就形成了一个循环。这就是这个过程被称为“事件循环(Event Loop)“的原因。

这里还有一张图来展示这个过程:

图中的 stack 表示我们所说的执行栈,web APIs 表示的是一些异步事件,而 callback queue 即事件队列。

2. 宏任务与微任务

以上的事件循环过程是一个宏观的表述,实际上因为异步任务之间并不相同,因此他们的执行优先级也有区别。不同的异步任务被分为两类:微任务(micro task)和宏任务(macro task)。

以下事件属于宏任务:

  • setInterval()
  • setTimeout()

一下事件属于微任务:

  • new Promise()
  • new MutationObserver()

前面我们介绍过,在一个事件循环中,异步事件返回结果会被放到一个任务队列中。然而,根据这个异步事件的类型,这个事件实际上会被对应到宏任务或者微任务中去。并且在当前执行栈为空的时候,主线程会优先查看微任务队列是否有事件存在。如果不存在,那么再去宏任务队列中取出一个事件并把对应的回调加入到当前执行栈中;如果存在,则会依次执行队列中事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的一个事件,把对应的回调加入当前执行栈...如此反复,进入循环。

我们只需要记住当当前执行栈执行完毕时,会立即处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次循环中微任务永远再宏任务之前执行。

这样就能解释下面这段代码的结果:

setTimeout(function () {
    console.log(1);
});

new Promise(function(resolve,reject){
    console.log(2)
    resolve(3)
}).then(function(val){
    console.log(val);
})

结果为:

2
3
1

转自:https://zhuanlan.zhihu.com/p/33058983

标签:异步,浏览器,js,任务,引擎,事件,栈中,执行
来源: https://www.cnblogs.com/aurora-ql/p/13732179.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有