JS 是单线程的,但是却能执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和任务队列(Task Queue)。

事件循环:

JS 会创建一个类似于 while (true) 的循环,每执行一次循环体的过程称之为 Tick。每次 Tick 的过程就是查看是否有待处理事件,如果有则取出相关事件及回调函数放入执行栈中由主线程执行。待处理的事件会存储在一个任务队列中,也就是每次 Tick 会查看任务队列中是否有需要执行的任务。

任务队列:

异步操作会将相关回调添加到任务队列中。而不同的异步操作添加到任务队列的时机也不同,如 onclick, setTimeout, ajax 处理的方式都不同,这些异步操作是由浏览器内核的 webcore 来执行的,webcore 包含上图中的 3 种 webAPI,分别是 DOM Binding、network、timer 模块。

  1. onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任务队列中。
  2. setTimeout 会由浏览器内核的 timer 模块来进行延时处理,当时间到达的时候,才会将回调函数添加到任务队列中。
  3. ajax 则会由浏览器内核的 network 模块来处理,在网络请求完成返回之后,才将回调添加到任务队列中。

主线程

JS 只有一个线程,称之为主线程。而事件循环是主线程中执行栈里的代码执行完毕之后,才开始执行的。所以,主线程中要执行的代码时间过长,会阻塞事件循环的执行,也就会阻塞异步操作的执行。只有当主线程中执行栈为空的时候(即同步代码执行完后),才会进行事件循环来观察要执行的事件回调,当事件循环检测到任务队列中有事件就取出相关回调放入执行栈中由主线程执行。

  • (所有代码都主线程里跑,主线程没代码了就在任务队列中读回调函数(异步操作)回到主线程里跑)
  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 主线程之外,还存在一个 "任务队列"(task queue)。只要异步任务有了运行结果,就在 "任务队列" 之中放置一个事件。
  3. 一旦 "执行栈" 中的所有同步任务执行完毕,系统就会读取 "任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  4. 主线程不断重复上面的第三步。("任务队列" 是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。)

    例1:
    var req = new XMLHttpRequest();
    req.open('GET', url);
    req.onload = function (){}; // 这两个异步方法就会在 ajax 完成后推入任务队列,再由主线程执行
    req.onerror = function (){};
    req.send();

    例2:
    setTimeout(function(){
    // 如果有大量的操作,可能会阻塞 UI 等,则可以使用 setTimeout 让这些操作在主线程把更重要的代码执行完毕之后,再来执行这里的操作。从而提高浏览器的性能。
    },0);// 设置为 0,也会有个最小间隔值,也会在主线程中的代码运行完成后,由事件循环从任务队列将回调添加到执行栈中才执行

    例3:
    // 事件循环测试。执行结果是 2-3-4-1,1在最后输出,说明事件循环是所有同步代码执行完后才开始执行的。

    'use strict';

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

    console.log(2);

    let end = Date.now() + 1000*5;

    while (Date.now() < end) {
    }

    console.log(3);

    end = Date.now() + 1000*5;

    while (Date.now() < end) {
    }

    console.log(4);

JS-线程、事件循环、任务队列的更多相关文章

  1. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...

  2. 浏览器中 JS 的事件循环机制

    目录 事件循环机制 宏任务与微任务 实例分析 参考 1.事件循环机制 浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图). 第一步:主线程(JS引擎线程)中执行 ...

  3. Node.js:事件循环

    ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...

  4. Node.js 的事件循环机制

    目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...

  5. js的事件循环绑定和jQuery的隐式迭代

    js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...

  6. js的事件循环和任务队列

    js 异步.栈.事件循环.任务队列 在开发中经常遇到js的异步问题,为了方便理解,记录下来,随时回顾. 以下的所有代码都是在浏览器环境下运行 在浏览器中js的运行是依赖浏览器js引擎来解析的,并且是在 ...

  7. JS:事件循环机制、调用栈以及任务队列

    点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...

  8. js的事件循环机制和任务队列

    上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别代表主线程中的任务和任务队列中的任务,那么此篇我们就来详细探讨这两者. 一.来张图感受一下 如果看完觉得一脸懵逼,请继续往 ...

  9. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  10. JavaScript之JS单线程|事件循环|事件队列|执行栈

    本博文基于知乎"JavaScript作用域问题?"一问,而引起了对JavaScript事件循环和单线程等概念与实践上的研究.深入理解. 一.概念 0.关键词:JavaScript单 ...

随机推荐

  1. Parameter setting for Jemeter Post method

    1. create CSV file note: the first line is parameter name 2. Add Controller Edit >Add >Logic C ...

  2. java 接口 以及 与抽象类的区别

    狭义概念 : Java 中的 interface 广义概念 : 对外提供规则的都是 接口 接口的定义方式 :  interface 接口名 { } 用类实现接口:       class 类名 imp ...

  3. Scrapy框架的应用

    一, Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍.所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有 ...

  4. Python 中的垃圾回收机制

    GC作为现代编程语言的自动内存管理机制,专注于两件事:1. 找到内存中无用的垃圾资源 2. 清除这些垃圾并把内存让出来给其他对象使用.GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在 ...

  5. java 标识接口的作用

    标识接口的作用 标识接口是没有任何方法和属性的接口.标识接口不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型. 标接口在Java语言中有一些很著名的应用,例如我们常用的Arra ...

  6. 事件对象e的实现原理

    转自:https://segmentfault.com/q/1010000007337410?_ea=1313467 事件对象传递原理 1.前置知识回顾 在讲传递原理前,我们先看看普通函数是如何传递参 ...

  7. Storm简介——初始Storm

    一.什么是Storm Strom是由Twitter开源的类似于Hadoop的实时数据处理框架.Strom是分布式流式数据处理系统,强大的分布式集群管理.便捷的针对流式数据的编程模型.高容错保障这些都是 ...

  8. Vue Cli3 TypeScript 搭建工程

    Vue Cli3出来也一段时间了,我想尝试下Vue结合TypeScript搭建个工程,感受下Vue下用TS...网上有一篇讲的非常详细的教程  vue-cli3.0 搭建项目模版教程(ts+vuex+ ...

  9. 基于 VirtualApp 结合 whale hook框架实现hook第三方应用

    要点 1. whale hook framework 使用示例: 2. 参考项目:VirtualHook: 3. 按照 VirtualHook 修改 VirtualApp: 4. 编写 hook pl ...

  10. 【知识强化】第七章 输入/输出系统 7.1 I/O系统基本概念

    那么下面,我们将要进入计算机组成原理的最后一章,也就是我们的第七章,输入输出系统的学习.那么这一部分内容呢,我们之前呢一直在提,但是并没有详细地讲解,那么进入到我们第七章输入输出系统这一部分,我们就要 ...