白话 event loop的理解

event loop ? microtask ? macrotask ? 不好意思,我记不住,关于这方面的解释以及深入理解一大堆的中英结合,中间穿插着各种 setImmediate、requestAnimationFrame。‘我才学,脑袋大,通俗点,886 Ctrl+W’。


我想用俗话说

我先把主要围绕的例子列出来,也主要是通过这个最常见代码去解释一下我对event loop的理解:

    for(var i = 0; i < 5; i++) {
        setTimeout(function() {
              console.log(i);
        },1000*i);
  }

A:哇,你个水货,先出来一个5 然后 一秒一个 5,面试经典题还用你教? (张学友的问候.jpg)

me: 好像还可以在深入一下....,比如:

  • 为什么每次都是5;
  • 为什么是你理解的1s一次;
  • 为什么用立即执行函数(IIFE)就可以解决, 以及ES6中的let。

我想,等我废话说完你可能会有个大概理解了,到时候我想基于这个理解再写一篇关于AMD的白话文实现。

上道具

我把一次任务的执行理解为上图两个部分

阻塞事件

js是单线程,在代码执行阶段对代码进行分类处理,按照我的理解就是:当我找到你的时候,你就必须去做或者立刻告诉我结果。就好比我去订餐,有没有位子就在此次通话内告诉我。
那我们的例子来说就是:

for(var i = 0; i < 5; i++) {}  
 => var i = 0;  {做点什么}(i++);  {做点什么}(i++);  {做点什么}(i++);  {做点什么}(i++);...
//当然会说了,明明还要 i<5 的判断了,这个里判断也算是阻塞。很小的一部分。

这里就是 就往 阻塞队列增加了5个事件(当然肯定不止5个,每个事件内部还有事件),并按照先进先出(堆)的原则去执行。

非阻塞事件

当程序读取到了非阻塞事件,将该事件如加入到当前的非堵塞队列,等待同一个任务队列中的阻塞队列执行结束后,再去执行非阻塞队列中的任务,当然也是先进先出

 setTimeout(function(){console.log('1')},500);      //A
 setTimeout(function(){console.log('2')},100);      //B
=>
2
1

不要以为B比A先出来,就以为B比A先执行。这个,肯定要讲。
根据列子来说:

     setTimeout(function() {
              console.log(i);
        },1000*i);

// 就是往 非阻塞队列 添加了 五个非阻塞时间
// 这个时候我们一定要区分 console.log(i)与 setTimeout(fn,1000*i)  中的 i;
//当然他们是同一个i,只是时刻不同,那么时刻不用是什么?

  • console.log(i)中的 i: 是当这个非阻塞事件可以执行的时候去获取的 i
  • setTimeout(fn,1000*i)中的 i : 是注册这个非阻塞事件并向非阻塞事件队列添加的时候的 i,这个I就是0 1 2 3 4(这一个跟开始我抛出的,为什么是你理解的1秒1次5有关);

整体分析

图解任务
  • 首先必须明确的是,非阻塞队列只有在对应的阻塞队列执行完毕后才能执行。
  • 非阻塞队列,并不一定是一次循环执行就能结束的,也就是说按照注册顺序执行,满足条件的事件执行回调并移除该队列。

解答

为什么输出console.log(i),输出5个5;

因为所有非阻塞队列中的fn0-fn4中都是 console.log(i);
根据js设计思想,只有当用到某个变量时,才去寻找这个变量的值,这个时候非阻塞队列是在阻塞队列执行完全之后再执行的;
那么这个时候的i已经经过了5个for循环5个i++从一开始的0变成了5,所以在fn0-fn5执行的时候console.log(i),i 的值 已经是5了。

为什么是你理解的1s一个5

首先它的确是 0s 5 ;1s 5 ;2s 5 ;3s 5 ;4s 5 ;
为什么又是1s一个5呢? 参照物
当你根据每个console .log(i)出现为基准,就如同大家都在一个房间,A出门走1步,B出门走2步,C出门走3步。。。
相对于ABC...每个人来说,他们之间的确相差了1步
但是相对这个房间来说,ABC...每个人相对于房间可就不是固定的1步了。
我在阻塞队列注册了五个非阻塞事件,谁告你这几个setTimeout之间有关系的。。。,
我一个人玩的setTimeout为什么要根据你的setTimeout结束才能玩?

解答:
阻塞队列执行的时候,注册了五个非阻塞事件,例如:
阻塞事件中通过setTimeout注册了一个非阻塞事件,以这个注册时间为基准,至少1000*i ms(这里的i肯定0 1 2 3 4 而不一直都是5,因为我注册事件的时候就要用到i,那就要拿到当时的i值)之后去执行这个fn(setTimeout里面的fn回调函数);
那么五次循环之后(阻塞队列执行完毕),实际上就是已经注册了五个不同时间节点非阻塞事件,虽然说可以说五个非阻塞事件注册时间基本上是同一个时间点,但是程序执行的确是要花费时间的,只能说太快,事件太少,所以我们基本可以理解为这个5个setTimeout注册几乎就在一个房间,而每次注册的时候已经告诉了这个回调函数至少多少ms之后执行(就是告诉ABC...要相对这个房间走多少步)。
所以,他们的确是针对注册这个非阻塞事件时 , 0s 5 ;1s 5 ;2s 5 ;3s 5 ;4s 5 ;

为什么用立即执行函数(IIFE)就可以解决, 以及ES6中的let

因为闭包

   for(var i = 0; i < 5; i++) {
       (function(j) {
              setTimeout(function() {
                   console.log(j);
             },1000*i);
       })(i)
      
 }

实际上就是每个非阻塞事件再执行的时候去查找变量,通过IIFE给setTimeout与for循环之间多加了一层向上查找变量的作用于,本来是

for循环为每个setTimeout多提供了一层独有的闭包环境

其实你可以试试 把加入 IIFE 的console.log( j )变成console.log( i );
结果就还是 ** 5 个 5 因为 IIFE提供的闭包环境中 只提供了一个 j 变量, 当没有找到 i 时 ,又得向上查找,这个时候就找到了阻塞事件**执行完毕之后的 i ,那还不就 5 嘛~

let 其实就是让每个for循环有自己作用域块,从** 5 个 console.log(i)对应一个 ** i (不加let)变成 5 个 console.log(i)对应5个 i ,这每个 i 并不是同一个了。


结束

写到这里,其实已经很长了,再写下去可能就要开始乏味了。那我再说两个小点吧

  • promise : 其实就是 阻塞事件干儿子,不管setTimeout在promise之前多少(当然我们这里说的是同一个任务),每次去注册非阻塞事件的时候,promise肯定是在阻塞队列结束之后立即去执行的,就好比 阻塞事件每次执行完了就会说 “干儿子(promise),我好了你赶紧到我后面来,别让setTimeout它们先跑了”
  • setTimeout(fn,times),setInterval(fn,times): 它们中的 times,并不是说 隔 **xxx ms ** 后去执行,而是至少 xxx ms 只执行,为什么呢,说太多写不下,自己慢慢体会。
溜了溜了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容