浏览器事件循环机制

没有异步机制会怎样

js是单线程的,如果没有异步机制,所有代码会同步执行。一些比较耗时的操作比如网络请求,会阻塞线程直到请求返回结果才会继续向下执行。如果这样js的执行效率会比较低,甚至导致页面卡死。所以必须加入异步机制以提升js线程执行效率。

怎么加入异步机制

单线程和异步是互斥的,所以js线程本身是没有异步能力的。但是浏览器赋予了js线程异步能力,浏览器不仅支持js主线程,还可以开辟出http请求线程、定时器触发线程、事件触发线程等多种幕后线程。js线程遇到http请求、定时器等任务,会把它们交给相应的幕后线程执行,js线程继续向下执行,http请求、定时器等任务完成后再把回调放入js队列中等待js线程调用。这样js线程就具备了异步的能力了。同时JS引入了Promise使单线程也具备了异步能力。

怎么调度队列中的任务

浏览器把任务分为两类:宏任务和微任务。js引擎线程发起的任务称为微任务,浏览器其它线程发起的任务称为宏任务。整体代码script会放到宏任务里;幕后线程执行的任务完成后会把对应的回调放到宏任务里;js主线程会把某些任务放到微任务里,比如:Promise.resolve().then(callback) js主线程会把callback放到微任务里。

js线程的一般调度策略是:js线程从宏任务中选取一个任务执行,执行完成后,逐个执行微任务中的任务直至微任务为空,然后再次从宏任务中选取一个任务执行,如此反复。js线程从宏任务中选取一个任务开始到执行完所有微任务为止称为一个事件循环。比如宏任务中有两个任务macro1, macro2,微任务中有三个任务micro1, micro2, micro3,那么调度顺序为:macro1 > micro1 > micro2 > micro3 > macro2。

分析一个例子:

setTimeout(function timout_1() {
  console.log("timout_1");
}, 0);

Promise.resolve().then(function then_1() {
  console.log("then_1");
});

Promise.resolve().then(function then_2() {
  console.log("then_2");
});

js线程执行前,宏任务里只有整体代码script,微任务里没有任务。按照一般调度策略:

  1. js线程首先从宏任务里选取整体代码script执行;
  2. 把setTimeout任务交给计时器线程,计时器线程会立刻往宏任务里加入一个tiemtimeou_1任务 ;
  3. js线程把then_1加入微任务;
  4. js线程把then_2加入微任务 ;
  5. 执行完宏任务里的整体代码script,接着要依此执行微任务里的任务,现在微任务里有then_1和then_2,js线程从微任务里选取then_1执行,控制台打印then_1;
  6. js线程从微任务里选取then_2执行,控制台打印then_2;
  7. 微任务里没有其它任务,所以第一次事件循环结束;
  8. js线程开启第二次事件循环,从宏任务中选取任务执行。此时宏任务里只有timeou_1任务,js线程选取timeou_1执行,控制台打印timeou_1;
  9. 执行完timeou_1,接着要依此执行微任务里的任务,现在微任务里没有任务,所以第二次事件循环结束;
  10. 此时宏任务、微任务都为空,js线程循环等待新任务。

事件回调任务优先级较高

宏任务中,任务一般会按照先进先出的原则进行调度,但是如果宏任务中同时存在事件触发线程触发的任务,则会优先调度该任务。

分析一个例子:

<!DOCTYPE html>
<html lang="en">
  <body>
    <button id="btn">button</button>
    <script>
      document.getElementById("btn").onclick = function handleClick() {
        console.log("click btn");
      };
      setTimeout(function timeoutFn() {
        console.log("timeoutFn");
      }, 0);
      document.getElementById("btn").click();
    </script>
  </body>
</html>
  1. js线程执行整体代码script;
  2. 为btn添加监听事件;
  3. 时间触发线程将timeoutFn加入宏任务;
  4. 触发点击btn事件,将handleClick加入宏任务;
  5. 执行完整体代码script,因为微任务为空,本次事件循环结束;
  6. 第二次事件循环,宏任务中同时存在时间触发线程回调timeoutFn和事件触发线程回调handleClick,虽然timeoutFn先进入宏队列但事件回调任务优先级高,优先调度handleClick,输出click btn。微任务中没有任务本次事件循环结束;
  7. 第三次事件循环,宏任务中只有timeoutFn,js线程选取 timeoutFn 执行,输出 timeoutFn。微任务中没有任务本次事件循环结束;
  8. 此时宏任务、微任务都为空,js线程循环等待新任务。

参考:

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

推荐阅读更多精彩内容

  • 前言 想要了解一门语言,最好的办法就是了解它的运行机制。掌握了运行机制,能够让我们在开发中少走许多弯路,写出高质量...
    moofyu阅读 346评论 0 1
  • 新建bat文件:*.bat 脚本文件,新建“文本文档”,修改文本文档文件后缀为 ".bat" 使用bat文件:无参...
    宇宙小神特别萌阅读 1,526评论 0 2
  • 目录:1、Hexo 启用next主题模板2、更改Next主题为中文3、增加标签页和分类页4、使用标签页和分类页5、...
    宇宙小神特别萌阅读 1,837评论 1 3
  • 宏定义对比函数的优点 要写好C语言,漂亮的宏定义是非常重要的。宏定义可以帮助我们防止出错,提高代码的可移植性和可读...
    fangyuu阅读 96评论 0 0
  • 2020-04-10 中原焦点团队 肖巧风 焦点解决初级网络班第21期 坚持第78天原创分享 总约练81次 挑战三...
    凤舞九天阅读 260评论 0 0