Event Loop

进程和线程

我们打开电脑可以边听歌边写代码,这就是多任务。但是多年前的电脑可是单核的,它其实是让各个任务交替运行,只是每个任务运行很短的时间就切换到下一个任务,这样子就好像并行。其实真正的多任务并行只能在多核CPU上。不过任务一般都远远多于核心,所以其实还是多任务交替执行
对于操作系统而言,一个任务就是一个进程。一个任务一般而言不会只干一件事,就像看电影,不可能先看完在听音吧,这么些子任务其实就是线程,它和多任务一样也是交替执行
举个栗子,我们打开浏览器一个页签就是创建了一个进程,然后这个进程里有渲染线程、JS引擎、http线程等等
可以把这俩当做单位,操作系统能够调度的单位。

程序是指令、数据以及其组织形式的描述,进程就是程序的实体,也是线程的容器

并发和并行

并行是指同时执行,这个无论是宏观还是微观,程序都是一起执行的
并发是指在一个时间段之内多个程序执行,这个还微观上是顺序执行的,宏观上是同时的

宏任务和微任务

  1. 宏任务(macrotask)也叫tasks,一些异步任务的回调会被放进这个队列等待后续被调用,包括:setTimeout、setInterval、setImmediate、I/O、requestAnimationFrame(浏览器)、UI rendering(浏览器)、MessageChannel、ajax、script(JS文件)、postMessage
  2. 微任务(microtask)也叫jobs,另外一些异步任务会掉会被放进这个队列,包括:Promise、Object.observe、MutationObserver、process.nextTick(Node)

执行栈

JS代码运行是在执行上下文里进行的。有三种情况:

  • 全局执行上下文,代码首先进入的环境,在浏览器里是Window对象
  • 函数执行上下文,函数被调用时的环境
  • eval执行上下文,它会产生自己上下文
    一般来说我们代码不止一个上下文,这时候我们就会有个来存储这么些上下文,先进后出。如下所示
栗子

其实这个浏览器里的可能还不是那么好理解,如下图所示:

console.log('script start');

setTimeout(function cb1() {
      console.log('setTimeout');
}, 0);

Promise.resolve().then(function cb2() {
      console.log('promise1');
}).then(function cb3() {
      console.log('promise2');
});

console.log('script end');

写了个小栗子,参见Jake Archibald 的Tasks, microtasks, queues and schedules

  • 入栈main()全局上下文,main()加入Tasks队列
  • 打印script start
  • cb1加入加入Tasks队列(因为setTimeout是异步任务,交由timer模块处理,因为是0所以立即(有一点点延迟,看各浏览器情况)加入)
  • cb2加入Jobs队列
  • 打印script end
  • 退栈main(),执行Jobs
  • Jobs入栈
  • 打印promise1
  • cb3加入Jobs队列(Jobs执行期间,加入的也算本轮次)
  • 退栈cb2Jobs移除cb2
  • cb3入栈
  • 打印promise2
  • 退栈cb3Jobs移除cb3
  • 一次事件循环完毕,这时候浏览器可能进行页面渲染
  • Tasks移除main
  • Taskstask入栈
  • 打印setTimeout
  • 退栈cb1Tasks移除cb1
    +程序执行完毕

栈的容量是有限制的,一旦存放过多,是会爆栈的

Tasks和Jobs交替入栈,区别在于Tasks里的先入栈,且单个入栈,Jobs的在栈空了被全部执行

Jobs执行期间新加入的job也算本轮次

任务队列

其实执行栈的时候就说到这了
JS是单线程源于JS出现为了解决用户互动一些简单任务,多线程的话就有复杂的同步问题
不过单线程就意味着需要排队,所以任务队列应运而生,只要先不管IO、http之类的任务,等到它们有了结果再回过头来继续执行。
任务分俩种,同步任务异步任务同步任务就是主线程上顺序执行的任务,异步任务就是不进入主线程,而是进入任务队列的任务。它们都有相应的模块去处理(DOM Binding、network、timer),就像setTimeout由timer模块处理,到点之后就会把回调函数加入到任务队列
异步执行机制如下:

  • 所有的同步任务都在主线程上执行,形成执行栈
  • 执行栈之外还有一个任务队列,只要异步任务完成了就会加入到任务队列
  • 执行栈空了就会任务队列里的任务,然后将其压入执行栈开始执行,只不过是先执行Tasks的队首,然后执行整个Jobs
  • 就是不断重复上三步

JS的异步本质上来看还是同步的

浏览器线程

浏览器通常有GUI渲染线程、JavaScript引擎线程、定时触发器线程、事件触发器线程、异步HTTP请求线程。以定时触发器线程为例,遇到setTimeout的话就会交给它来处理,到点就加到tasks队列

后语

其实到这已经明白了,它是宿主环境为了解决JS单线程运行不阻塞的一种机制。
不过上面所诉其实都是浏览器的表现,即热式一种机制,不同的宿主自然也不一定一样的

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

推荐阅读更多精彩内容