为什么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. jquery 拓展函数集

    方式: 通过拓展在调用$()时返回的包装器 1.将函数绑定到$.fn $.fn.disable = function(){ return this.each(function(){ if (typeo ...

  2. Python基础-模块与包

    一.如何使用模块 上篇文章已经简单介绍了模块及模块的优点,这里着重整理一下模块的使用细节. 1. import 示例文件:spam.py,文件名spam.py,模块名spam #spam.py pri ...

  3. 在WinServer上安装小红伞杀毒软件的经验总结

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在WinServer2008或WinServer2012不能直接安装小红伞杀毒软件的免费版,需要安装服务器版.我手头并 ...

  4. Java全系列帮助文档下载

    JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和应用程序的程序开发环境.它由一个处于操作系统层之上的运行环境还有开发者编译,调试和运 ...

  5. 关于Flume以及Kafka理解

  6. 微信小程序——初始化一个小程序项目

    最近准备学习一下微信小程序,因为之前有react native项目经验,学习起来应该困难不大 微信小程序官网地址:https://mp.weixin.qq.com/debug/wxadoc/dev/i ...

  7. js 获取URL中参数

    function getQueryString() { var result = location.search.match(new RegExp("[\?\&][^\?\& ...

  8. devexpress chart 散点图加载并分组显示(可以自定义颜色 同组中的点颜色相同)

    this.dChart.Diagram.Series.Clear();//清空图的内容 var groups = result.GroupBy(itm => itm["flag&quo ...

  9. 【转】winrar命令行详解

    从命令行也可以运行 WinRAR 命令,常规的命令行语法描述如下: WinRAR  <命令> -<开关1> -<开关N> <压缩文件> <文件.. ...

  10. 《C++ Primer Plus》读书笔记之——处理数据

    本文旨在记录在阅读<C++ Primer Plus>第五版的过程中,一些重点的知识点,方便以后查阅.本文将不断更新...... 一.第三章 处理数据 1.无符号整型不能存储负数值,其优点是 ...