并发模型可视化描述

model.svg

如上图所示,Javascript执行引擎的主线程运行的时候,产生堆(heap)和栈(stack),程序中代码依次进入栈中等待执行,

若执行时遇到异步方法,该异步方法会被添加到用于回调的队列(queue)中【即JavaScript执行引擎的主线程拥有一个执行栈/堆和一个任务队列】。

栈(stack) : 函数调用会形成了一个堆栈帧
堆(heap) : 对象被分配在一个堆中,一个用以表示一个内存中大的未被组织的区域。
队列(queue) : 一个 JavaScript 运行时包含了一个待处理的消息队列。每一个消息都与一个函数相关联。

当栈为空时,则从队列中取出一个消息进行处理。这个处理过程包含了调用与这个消息相关联的函数(以及因而创建了一个初始堆栈帧)。

当栈再次为空的时候,也就意味着该消息处理结束。

为了更清晰地描述Event Loop,参考下图的描述:

model.png

首先,我们对图中的一些名词稍加解释

  1. queue : 如上文的解释,值得注意的是,除了IO设备的事件(如load)会被添加到queue中,用户操作产生 的事件(如click,touchmove)同样也会被添加到queue中。队列中的这些事件会在主线程的执行栈被清空时被依次读取(队列先进先出,即先被压入队列中的事件会被先执行)。
  2. callback : 被主线程挂起来的代码,等主线程执行队列中的事件时,事件对应的callback代码就会被执行

【注:因为主线程从"任务队列"中读取事件的过程是循环不断的,因此这种运行机制又称为Event Loop(事件循环)】

下面我们通过setTimeout来看看单线程的JavaScript执行引擎是如何来执行该方法的。

  1. JavaScript执行引擎主线程运行,产生heap和stack
  2. 从上往下执行同步代码,log(1)被压入执行栈,因为log是webkit内核支持的普通方法而非WebAPIs的方法,因此立即出栈被引擎执行,输出1
  3. JavaScript执行引擎继续往下,遇到setTimeout()t异步方法(如图,setTimeout属于WebAPIs),将setTimeout(callback,5000)添加到执行栈
  4. 因为setTimeout()属于WebAPIs中的方法,JavaScript执行引擎在将setTimeout()出栈执行时,注册setTimeout()延时方法交由浏览器内核其他模块(以webkit为例,是webcore模块)处理
  5. 继续运行setTimeout()下面的log(3)代码,原理同步骤2
  6. 当延时方法到达触发条件,即到达设置的延时时间时(5秒后),该延时方法就会被添加至任务队列里。这一过程由浏览器内核其他模块处理,与执行引擎主线程独立
  7. JavaScript执行引擎在主线程方法执行完毕,到达空闲状态时,会从任务队列中顺序获取任务来执行。
  8. 将队列的第一个回调函数重新压入执行栈,执行回调函数中的代码log(2),原理同步骤2,回调函数的代码执行完毕,清空执行栈
  9. JavaScript执行引擎继续轮循队列,直到队列为空
  10. 执行完毕
    console.log(1);
setTimeout(function() {
console.log(2);
},5000);
console.log(3); //输出结果:
//1
//3
//2复制代码

Macrotasks 和 Microtasks

基本上,一个完整的事件循环模型就讲完了。现在我们来重点关注一下队列。
异步任务分为两种:Macrotasks 和 Microtasks。

  • Macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering
  • Microtasks: process.nextTick, Promises, Object.observe(废弃), MutationObserver

Macrotasks 和 Microtasks有什么区别呢?我们以setTimeout和Promises来举例。

    console.log('1');
setTimeout(function() {
console.log('2');
}, 0);
Promise.resolve().then(function() {
console.log('3');
}).then(function() {
console.log('4');
});
console.log('5');
//输出结果:
//1
//5
//3
//4
//2复制代码

原因是Promise中的then方法的函数会被推入 microtasks 队列,而setTimeout的任务会被推入 macrotasks 队列。在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtasks 队列清空。
结论如下:

  1. microtask会优先macrotask执行
  2. microtasks会被循环提取到执行引擎主线程的执行栈,直到microtasks任务队列清空,才会执行macrotask

【注:一般情况下,macrotask queues 我们会直接称为 task queues,只有 microtask queues 才会特别指明。】

作者:网易考拉前端团队
链接:https://juejin.im/post/59b499a8f265da0656043567
来源:掘金

JavaScript并发模型与Event Loop (转载)的更多相关文章

  1. javascript运行模式:并发模型 与Event Loop

    看了阮一峰老师的JavaScript 运行机制详解:再谈Event Loop和[朴灵评注]的文章,查阅网上相关资料,把自己对javascript运行模式和EVENT loop的理解整理下,不一定对,日 ...

  2. JavaScript Concurrency model and Event Loop 并发模型和事件循环机制

    原文地址:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop JavaScript 有一个基于 event loop 的 ...

  3. 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)

    JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...

  4. javascript基础修炼(5)—Event Loop(Node.js)

    开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一. 一道考察异步知识的面试题 题目是这样的,要求写出下面代码的输出: setTimeout(() => { co ...

  5. javascript的执行机制—Event Loop

    既然今天要谈的是javascript的事件循环机制,要理解事件循环,首先要知道事件循环是什么. 我们先从一个例子来看一下javascript的执行顺序. <script> setTimeo ...

  6. JavaScript 运行机制以及Event Loop(事件循环)

    一.JavaScript单线程 众所周知JavaScript是一门单线程语言,也就是说,在同一时间内JS只能做一件事.为什么JavaScript不能有多个线程呢?这样不是能够提高效率吗? JavaSc ...

  7. JavaScript 的核心机制——event loop(最易懂版)

    前言 javascript从诞生之日起就是一门单线程的非阻塞的脚本语言. 非阻塞就是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如ajax事件)时,主线程会挂起(pen ...

  8. [更新]单线程的JS引擎与 Event Loop

    先来思考一个问题,JS 是单线程的还是多线程的?如果是单线程,为什么JavaScript能让AJAX异步发送和回调请求,还有setTimeout也看起来像是多线程的?还有non-blocking IO ...

  9. 从event loop规范探究javaScript异步及浏览器更新渲染时机

    异步的思考 event loops隐藏得比较深,很多人对它很陌生.但提起异步,相信每个人都知道.异步背后的“靠山”就是event loops.这里的异步准确的说应该叫浏览器的event loops或者 ...

随机推荐

  1. cgi fast-cig php-fpm

    cgi 通用网关接口,接受到动态请求,web服务器会根据这次请求的内容,然后会fork一个新进程来运行, 这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进 ...

  2. {"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}

    ElasticSearch-head 查询报 406错误码 {"error":"Content-Type header [application/x-www-form-u ...

  3. 河北省重大技术需求征集系统原型(MVC框架业务流程简介)

    这段时间了解了一些MVC框架. 一.MVC简介 MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式.它的模式是JSP + se ...

  4. Android 开发 CoordinatorLayout 协调者布局 与 ConstraintLayout约束布局 两者的关系

    在摸索新技术是发现CoordinatorLayout 与 ConstraintLayout 会有冲突关系,所以就研究了一下他们之间的不兼容,被影响的方面.其实某种程度上来说是CoordinatorLa ...

  5. [持续交付实践] Jenkins 中国用户大会参会见闻

    前言 上周日在上海召开了Jenkins中国用户大会(Jenkins User Confluence China),这应该是Jenkins在中国第一次举办吧.Jenkins的创始人Kohsuke Kaw ...

  6. Celery异步的分布式任务调度理解

    什么是Celery呢? Celery是一个用Python开发的异步的分布式任务调度模块. Celery本身不包含消息服务,使用第三方消息服务,也就是Broker,来传递任务,目前支持的有Rebbimq ...

  7. blade 学习

    一.目录构造样式 . └── workspace ├── BLADE_ROOT ├── build64_release ├── client │   ├── BUILD │   └── client. ...

  8. loadrunner代理录制脚本

    1.打开loadrunner录制脚本选项: 2.start  recording弹窗选择options: 3.设置loadrunner端口,可自定义:后面的浏览器设置代理需要用到此处设置的端口号: 4 ...

  9. Ubuntu安装后上网问题,

    首先VMware网络配置详解一:三种网络模式简介 http://www.cnblogs.com/gylei/archive/2012/04/06/2435087.html 很详细. 此处讲述通过桥接来 ...

  10. java面试题复习(二)

    //我又回来了 11.数组有没有length()方法?String有没有length()方法? 数组只有length属性,String有length()方法.注意:JavaScript获取字符串长度使 ...