为什么JavaScript是单线程?

JavaScript的一大特点就是单线程, 同一时间只能做一件事情,主要和它的用途有关, JavaScript主要是控制和用户的交互以及操作DOM。注定它是单线程。 假如是多个线程, 一个移除DOM节点,一个新增DOM节点,浏览器以谁的为准呢?

什么是执执行栈呢?

函数的调用就会形成一个栈帧。当执行栈都为空的时候,主线程就会处于空闲状态。

   function fn2(x, y) {
      return x + y
   } 

   function fn1(z) {
     let a = 10
     return fn2(a, z)
   }

   console.log(fn1(5)) // 15

以上代码: fn1 函数调用时会创建一个执行栈,栈中包含fn1的参数和局部变量。当 fn1 调用 fn2 时, 第二个执行栈就会被创建, 并且压入到第一个执行栈之前。 栈中包含了 fn2的参数和全局变量。当 fn2执行完返回时,最前面的执行栈就会被弹出。剩下 fn1 函数的调用帧, 当fn1 函数执行完并返回时, 执行栈就空了。

任务队列

任务队列主要用户挂起等待中的任务(异步任务)。
JavaScript是单线程, 意味着所有的任务需要排队, 前一个任务执行完,才能进行下一个任务。 AJAX就是典型的异步任务,需要调用HTTP线程,然后发送request请求,再是等待服务端的响应。在结果没有返回执行,后面的代码是不会执行的,这会给用户一种网站卡的现象。

因此, JavaScript 分为 同步任务在主线程上排队执行的任务,也就是前面执行完毕,才能执行下一个的任务。 异步任务是指它不会进行主线程,不会影响后续代码的执行,而是进入任务队列,当异步任务执行有了结果,就会在任务队列中放置一个事件,等主线程空闲(执行栈为空,同步任务执行完毕),通知任务队列进入主线程执行。

微任务和宏任务

任务队列中的异步任务分为 微任务宏任务
常见的微任务有: process.nextTickPromiseMutationObserver监听DOM的变化。

常见的宏任务: setTimeoutsetIntervalsetImmediatescript中整体的代码、 I/O操作UI渲染等。

微任务和宏任务的区别:

  • 微任务进入主线程执行是一队一队的, 而宏任务进入主线程是一个一个的。
  • 微任务是在主线程空闲时批量执行, 宏任务是在事件循环下一轮的最开始执行

例子: 以下代码的打印结果

    console.log(1)
    setTimeout(function() {
        console.log(2)
    })

    Promise.resolve()
        .then(function() {
            console.log(3)
        })

    console.log(4)

   // 打印结果: 1 4 3 2

整个的执行过程:

    stack(执行栈)、Micro(微任务)、Macro(宏任务)

    1.初始状态: stack:[], Micro: [], Macro: [script]。执行栈为空, 微任务为空, 宏任务队列中有一个整体的 script代码 

    2. 主线程开始执行, 遇到console.log(1), 首先会打印 1 

    3. 继续向下执行,遇到 setTimeout异步任务,就将其加入到Macro(宏任务)队列中。等待执行 

    4. 继续向下执行, 遇到 Promise.resolve也是一个异步任务,单它是微任务,将其加入 Micro(微任务)队列中,等待着行 

    5. 解析console.log(4), 并且打印4。 当主线程执行完打印的结果依次是 1 和 4。

    6. 这时候主线程就会问 任务(异步)队列,有没有微任务要执行,将所有的 Micro(微任务)加入执行栈执行, 打印结果 3

    7. 微任务执行完了, 就开始下一轮事件循环, 将第一个 Macro(宏任务)压入执行栈执行, 再次打印 2。 

Event Loop事件循环

只要主线程一空闲就会将 "任务队列中的异步任务"依次压入执行栈, 这个过程是循环不断的,所以整个运行机制称之为 Event Loop(事件循环)。

执行栈中(stack)的代码(同步任务),总是在读取"任务队列"(异步任务)之前执行。

图示

参考文章

JavaScript Event Loop和微任务、宏任务的更多相关文章

  1. Event Loop我知道,宏任务微任务是什么鬼?

    在介绍宏任务和微任务之前,先抛出一个问题.相信大家在面试的时候,会遇到这样的相似的问题: setTimeout(function(){undefined console.log('1') }); ne ...

  2. javascript event loop

    原文: https://blog.csdn.net/sjn0503/article/details/76087631 简单来讲,整体的js代码这个macrotask先执行,同步代码执行完后有micro ...

  3. JavaScript event loop事件循环 macrotask与microtask

    macrotask  姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...

  4. javaScript Event Loop + NodeJs问题解析

    http://www.ruanyifeng.com/blog/2014/10/event-loop.html https://github.com/ElemeFE/node-interview/tre ...

  5. 深入理解 JavaScript 事件循环(一)— event loop

    引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...

  6. JavaScript事件循环(Event Loop)机制

    JavaScript 是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决定 ...

  7. JavaScript 事件循环 — event loop

    引言 相信所有学过 JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的异步概念 .在初期许多人会把异步理解成类似多线程的编程模式 ...

  8. 【js基础修炼之路】- 微任务,宏任务和Event-Loop

    一段代码让你了解Event-Loop console.log(1); setTimeout(() => { console.log(2); }, 0); new Promise((resolve ...

  9. event loop 与 vue

    结论 对于event loop 可以抽象成一段简单的代码表示 for (macroTask of macroTaskQueue) { // 1. Handle current MACRO-TASK h ...

随机推荐

  1. 记录开发Nodejs c++ addon的一些经验(一、技术栈)

    Nodejs c++ addon 是用c++去编写Nodejs的插件 技术栈: 1.node-gyp 一个用于把c++文件编译成node可执行文件的库 2.v8 google v8引擎 用于处理c++ ...

  2. Python入门-再谈编码

    一.小数据池 在说小数据池之前. 我们先看一个概念. 什么是代码块: 根据提示我们从官方文档找到了这样的说法: A Python program is constructed from code bl ...

  3. vue-cli脚手架之其他文件解释

    好了,脚手架目录中重要的文件基本都介绍了,但还有一个不太注意到的文件没有解释,这里也说明一下. config文件夹下的index.js,作用是不同开发环境下的参数配置(可选项很多,生产环境.开发环境. ...

  4. html中块级元素和行内元素

    块级元素和行内元素的三个区别 1.行内元素与块级元素直观上的区别: 行内元素会在一条直线上排列,都是同一行,水平方向排列 块级元素独占一行,垂直方向排列.块级元素从新行开始结束接着一个断行 2.块级元 ...

  5. 【阿里云产品公测】性能测试服务PTS的初步尝试

        性能测试服务PTS,对于像我这样对测试毫无概念的新手来说,这服务真的太好了,使用简单,官方教程又明细,连我这样的新手一看都明白了怎样使用. _%GGl$kH   下面是我来简单尝试一下,更多功 ...

  6. 【Android】修改包名

    工程写的差不多了才发现原来用的包名还是自己尝试性的进行写代码的时候用到的.但apk的发布,google map api的申请等等方面都需要用到一个比较规范的包名.这就涉及到修改包名的问题. 包名一开始 ...

  7. string 替换字符串

    C++的string提供了replace方法来实现字符串的替换,但是对于将字符串中某个字符串全部替换这个功能,string并没有实现,我们今天来做的就是这件事.首先明白一个概念,即string替换所有 ...

  8. Ubuntu14.04下如何安装Python爬虫框架Scrapy

    按照官方文档的说明,安装scrapy 需要以下程序或者库: (1).Python 2.7 (2).lxml. Most linux distributions ships PRepackaged ve ...

  9. .Net ->> iTextSharp工具读取PDF文本内容

    分享一个开源的C#DLL,可以读取PDF文本内容. 地址:http://sourceforge.net/projects/itextsharp/ 这里还有相关的链接:http://www.codepr ...

  10. LeetCode-Subsets ZZ

    LeetCode:Subsets Given a set of distinct integers, S, return all possible subsets. Note: Elements in ...