事件循环机制

事件循环机制

JavaScript是一门单线程,非阻塞的脚本语言

单线程: 只有一条主线程来处理所有的任务

非阻塞:当代码需要进行异步任务的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定的规则去执行相应的回调

那么非阻塞是在js引擎中是怎么实现的呢?——event loop(事件循环机制)

详解JavaScript中的Event Loop(事件循环)机制

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

1.执行栈与事件队列

变量的存储位置:

  1. 堆:存放一些对象。
  2. 栈:存放一些基础变量以及对象的指针。

执行上下文(context):

    当我们调用一个方法的时候,js会生成一个与这个方法相对应的执行环境,这个执行环境就是执行上下文,执行上下文存在这个方法的私有作用域

!执行栈:

    **在js中,当一系列方法被一次调用的时候,因为js是单线程的,同一时间只能执行一个任务,于是这些方法会被排队在一个单独的地方**,这个地方就是执行栈。

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

    要注意的是,上面已经提到当一个方法执行的时候会向执行栈中加入这个方法的执行环境,在这个执行环境中还可以调用其他方法,甚至是自己,其结果不过是在执行栈中再添加一个执行环境。这个过程可以是无限进行下去的,除非发生了栈溢出,即超过了所能使用内存的最大值。

以上的过程说的都是<u>同步代码</u>的执行。**

那么当一个异步代码(如发送ajax请求数据)执行后会如何呢?前文提过,js的另一大特点是非阻塞,实现这一点的关键在于下面要说的这项机制——事件队列(Task Queue)

说白了就是,js的非阻塞特点是通过事件队列(Task Queue)实现的

!事件队列:

    当js引擎遇到一个异步事件后并不会一直等待其返回结果,而是将这个事件挂起,继续执行执行栈中的其他任务,当一个异步事件返回结果后,js会将这个事件加入到与当前执行栈不同的另一份队列,我们称之为事件队列(也有叫异步队列的)

!事件循环(Event Loop):

    **被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务(同步任务)都执行完毕, 主线程处于闲置状态时,主线程才会去查找事件队列是否有任务。如果有,那么主线程会从事件队列中取出排在第一位的事件任务,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码,如果里面存在异步代码,则把里面的异步代码挂到事件队列里,如此反复,这样就形成了一个无限的循环。**这就是这个过程被称为“事件循环(Event Loop)”的原因。

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

img

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

在事件队列中,异步任务又分两类,<u>宏任务和微观任务</u>,执行优先级是微任务>宏任务**

2.宏任务和微任务

宏任务(macrotask )和微任务(microtask)

宏任务一般是:包括整体代码script中的代码setTimeout()setInterval()I/OUI render
微任务主要是Promise.then()Object.observe()MutationObserver()

事件队列的工作流程:

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

    ***<u>换一种解释就是</u>***

    在挂起任务时,`JS 引擎`会将所有任务按照类别分到这两个队列中,开始执行事件队列中的任务时,首先判断是否有微任务存在,有微任务则先取出微任务中的首个任务到执行栈中执行,执行完毕后在回去判断事件队列中是否还有微任务,判断事件队列不存在微任务后,再执行事件队列中的宏任务,在宏任务的队列中取出第一个任务,将它放到执行栈中执行,如果宏任务中还有异步操作,则将这些异步操作接着挂载到事件队列中,当该宏任务在执行栈中结束后,再去事件队列中判断是否有微任务,有则先处理微任务,没有则再取宏任务队列中最前面的任务,放到执行栈中执行,周而复始,直至两个队列的任务都取完。

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

宏任务与微任务关系图:

img

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容