浅谈event-loop

其实这是一篇很久之前就想发的博客了,最近有时间正好整理了下,我们先看一张图:


浏览器引擎简图.png

其中Memory Heap是内存分配的地方,我们这里不谈。Call Stack就是引擎的调用栈,我们都知道js是一个单线程的语言,所以调用栈有且只有一个且只会顺序做某一件事,那么调用栈是什么呢?其实调用栈是一种数据结构,它基本上记录了程序中的位置。如果我们进入函数,我们将它放在堆栈的顶部。如果我们从函数返回,我们会弹出堆栈的顶部。这就是所谓的压栈和出栈~

  • 浏览器中的异步

试想一下如果所有的代码都是同步按顺序执行的情况页面将会发生什么?用户点击不能及时响应,请求数据没返回之前页面一直白屏等等。为了解决这一个问题就有了一个叫做Web API的东西,它完全是由浏览器提供。然后有了我们的event-loop和回调队列。如下图:


image.png

event-loop的概念大家自行百度,我们这里用一段代码简单的看下loop模型。

  function multiply(x,y) {
    return x*y
  }
  function printSquare(x) {
    const s = multiply(x,x)
    console.log(s)
  }
  printSquare(5);

这些代码其实是属于一个event-loop的,这次event-loop的调用栈如下图所示:

image.png

我们可以知道当代码执行到最后一行的时候本次event-loop完毕,由于没有异步的任务队列,所以还是比较好理解的。

  • 堆栈溢出

当一个event-loop执行时调用栈超出本身大小时。比如以下代码:

function fn() {
  fn();
};
fn();
image.png
  • 微任务,宏任务

首先我们要知道什么样的情况会产生微任务:MutationObserver,Promise
宏任务:setTimeout,setInterval,I/O,鼠标事件等
那么宏任务和微任务同样都是异步的任务队列,区别如下:

  1. 执行时机不同,宏任务在下一次event-loop中,微任务在本次event-loop结束后执行

2.一次event-loop只会执行属于一个宏任务队列,而微任务可以一直执行

我们用几行代码来验证下:

function multiply(x,y) {
    return x*y
  }
  function printSquare(x) {
    const s = multiply(x,x)
    setTimeout(() => {
      console.log('我是另外一个event-loop')
    }, 0)
    new Promise((resolve, reject) => {
      console.log('hah')
      resolve(() => {})
    }).then(() => {
      console.log('heh')
    })
    new Promise((resolve, reject) => {
      console.log('haha')
      resolve(() => {})
    }).then(() => {
      console.log('hehe')
    })
  }
  printSquare(5);
  console.log('我是一个event-loop')

打印如下:

image.png

我们针对结果来分析下:
在分析之前我们要先明白一个东西,promise虽然是微任务,但是promise的executor部分确是同步执行的,参考MDN:


image.png

首先是第一个event-loop:
1.顺序执行两个promise的executor
2.执行最后一行console
第二个event-loop:
1.执行完所有微任务
第三个event-loop:
1.执行setTimeout回调部分

  • 如何验证所有的微任务都是在一个event-loop执行,而宏任务不是

其实这个也比较容易验证,比如我们递归调用promise的时候其实是和栈溢出的情况一样的,但是当我们如下调用的时候:

  function printSquare() {
    console.log('我是另外一个event-loop')
    setTimeout(() => {
      printSquare()
    }, 0)
  }
  printSquare();

浏览器是不会栈溢出的~

  • web-worker

最后我们谈一下web-worker,web-worker和异步的模型不太一样。因为根据以上我们知道虽然我们有event-loop,有队列,但是执行栈始终都只有一个,异步的队列最终也是在调用栈中执行的,调用栈中如果调用的一个函数处理了一段很复杂的逻辑就会影响下一次用户的人机交互,那么这时候web-worker就派上用场了,大家可以把这种庞大的运算逻辑放在web-worker中处理,比如图片算法对比等等。这时候就不会一直占用当前调用栈了~

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

推荐阅读更多精彩内容