为什么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. Git更新或提交出错的解决办法

    一.舍弃本地代码,用远端版本覆盖本地版本. 当自己本地修改很少,更新代码出现冲突时,“error: Your local changes to the following files would be ...

  2. Magisk+Xposed+Root switch+Pokémon GO

    If you follow Android Police, there's a good chance you've got a rooted device, whether it be an eas ...

  3. Vue2.0中的系统指令

    v-on注册事件 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  4. [PE格式分析] 2.IMAGE_DOS_HEADER

    typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number 固定为"MZ" ...

  5. androidcarsh

    package com.oval.cft; import java.io.File;import java.io.FileOutputStream;import java.io.PrintWriter ...

  6. Maximum Subarray解题报告zz

    http://fisherlei.blogspot.com/2012/12/leetcode-maximum-subarray.html Find the contiguous subarray wi ...

  7. 玩转Windows/Linux tftp命令

    tftp很好理解, 主要用来传文件, 下面以我的操作来谈谈tftp中最重要的几个命令. 一. Windows上的sftp命令(据说Linux上也是这样, 当然此处是指非嵌入式的Linux) 步骤: a ...

  8. typeof操作符和instanceof操作符的区别 标签: JavaScript 2016-08-01 14:21 113人阅读 评论(

    typeof主要用于检测变量是不是基本数据类型 typeof操作符是确定一个变量是字符串.数值.布尔类型,还是undefined的最佳工具.此外,使用typeof操作符检测函数时,会返回"f ...

  9. June 19th 2017 Week 25th Monday

    Everyone is dissatisfied with his own fortune. 人对自己的命运总是感到不满足. We always want more, even when we hav ...

  10. 轻量级自动化运维工具Fabric的安装与实践

    一.背景环境 在运维工作中,经常会遇到重复性的劳动,这个时候为了效率就必须要使用自动化运维工具. 这里我给大家介绍轻量级自动化运维工具Fabric,Fabric是基于Python语言开发的,是开发同事 ...