JavaScript 事件循环(Event Loop)

一、概念

一种计算机系统的运行机制,JavaScript采用这种机制,来解决单线程运行带来的一些问题
要理解Event Loop,就要从程序的运行模式讲起,运行以后的程序叫"进程",一般情况下,一个进程只能执行一个任务

如果有很多任务需要执行,不外乎三种解决方法

  1. 排队,因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。
  2. 新建进程,使用 fork 命令,为每个任务新建一个进程。
  3. 新建线程,因为进程太耗费资源,所以如今的程序往往一个进程可以包含多个进程,由线程去完成任务。

JavaScript是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",因为JavaScript停不下来,也就无法响应用户的行为。

JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)

二、功能

负责执行代码、收集和处理事件以及执行队列中的子任务

三、原理

1. 执行栈与事件队列

  • JavaScript代码执行的时候,不同的变量存放于内存中不同的位置:堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。 但是我这里说的执行栈和上面这个栈的意义却有些不同。

  • 当我们调用一系列方法的时候,因为js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方函数调用形成了一个由若干帧组成的栈(先进后出),称之为执行栈。当脚本开始执行的时候,代码同步压入栈中,函数方法从顶部开始执行,当前执行方法结束后,js会退出这个执行环境并销毁,然后进入到下一个执行环境(如果还有的话),这个过程会反复进行,直到全部执行完毕。这个过程是可以无限进行的,除非发生了栈溢出。这些就是同步代码执行。

  • 如果发送一个异步请求的话,就涉及到事件队列了
    js引擎遇到一个异步事件后,不会一直等待执行结果出来,而是将这个事件挂起,继续走执行栈中的其他任务。然后当这个异步事件结果返回来之后,js会将这个事件加入与当前执行栈不同的另一个队列,这个就叫事件队列(也就是异步事件返回结果时按先后顺序排列)。当它被放入事件队列中时不会立即执行其回调,而是等待当前执行栈中所有的任务都执行完毕了,主线程处于闲置的时候,才回去查找事件队列中是否有需要执行的任务,如果有,就会从找那个取出排在第一位的事件,把该事件对应的回调放入执行栈中,然后执行其同步代码,执行结束后,如果闲置了,再次查找,如此循环。这个过程就是“<font color="#e43938">事件循环(Event Loop)</font>”

2. 宏任务与微任务 (macro task && micro task)

事实上,异步任务之间也有执行顺序的区别,不用的异步任务分为两类:微任务(micro task) 和 宏任务(macro task)
属于宏任务的有:

setInterval()
setTimeout()
I/O
requestAnimationFrame (晚于微任务执行)

微任务:

new Promise()
new MutationObserver()
process.nextTick()

重点:当前执行栈执行完毕时,会先处理所有微任务队列中的事件,然后再去宏任务队列事件,同一次事件循环中,微任务永远在宏任务之前执行

console.log(1);

setTimeout(()=> {
    console.log(2);
    process.nextTick(()=> {
        console.log(3);
    });
    new Promise(resolve=> {
        console.log(4);
        resolve()
    }).then(()=> {
        console.log(5);
    })
})

process.nextTick(()=> {
    console.log(6);
})

new Promise(resolve=> {
    console.log(7);
    resolve()
}).then(()=> {
    console.log(8);
})

setTimeout(()=> {
    console.log(9);
    process.nextTick(()=> {
        console.log(10);
    })
    new Promise(resolve=> {
        console.log(11);
        resolve()
    }).then(()=> {
        console.log(12);
    })
})

console.log(13);

// 1 7 13 6 8 2 4 3 5 9 11 10 12

一个 web worker 或者一个跨域的 iframe 都有自己的栈、堆和消息队列。两个不同的运行时只能通过 postMessage 方法进行通信。如果另一个运行时侦听 message 事件,则此方法会向该运行时添加消息。

四、最后

以上基本输入常识内容,还有浏览器与node环境的部分差异,这些都没做深入研究,暂时做个笔记了结。后续发现问题订正

---------------2020.04.10

相关内容链接:https://www.ruanyifeng.com/blog/2013/10/event_loop.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop

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

推荐阅读更多精彩内容