单线程

众所周知,JS是单线程的语言,之所以是单线程,用一句烂大街的话就是,如果两个线程同时操作一个DOM节点,那么该以哪个为准呢,虽然多线程也有办法解决,但是js毕竟是浏览器脚本语言,不需要那么复杂

但是单线程遇到多个任务,需要排队执行,如果遇到定时器任务或者ajax请求等等,那会严重影响用户体验,于是将异步任务暂时挂起,先运行后面的任务,等异步操作返回了结果,再来执行

所以把任务分为两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous),同步任务是指在主线程上排队的任务,只有前一个任务执行完毕,才会执行后面的任务,异步任务是指不进入主线程,而是进入任务队列(task queue),当任务队列通知主线程某一个异步任务可以执行的时候,才会进入主线程执行。

同步 异步执行机制

1 所有的同步任务都在主线程上执行,形成一个技术栈(execution context stack)

2 主线程之外,还有一个任务队列(task queue)

3 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,里面的异步任务就会结束等待状态,进入执行栈,开始执行

4 主线程会不断的重复上面的三部内容
那么js是如何处理异步呢:通过渲染进程(浏览器内核)多线程实现异步?

进程

程序运行的实例,同一个程序可以产生多个进程,一个进程可以包含多个线程

线程

操作系统能够进行运算调度的最小单位,一个只能执行一个任务,有自己的调用栈,寄存器环境,同一个进程的线程共享进程资源

浏览器进程:Browser进程,渲染进程(浏览器内核),GPU进程,网络进程,插件进程

渲染进程(浏览器内核)

GUI线程

负责渲染页面,解析html,css,构建DOM树和渲染树,当界面需要重绘(repaint)或者由于某种操作引发回流(reflow)时,该线程就会执行

JS引擎线程

解析JS,和GUI互斥,因为JS也可以操作DOM,如果两个线程同时操作DOM,可能会出现不可预期的结果,所以JS引擎运行期间,GUI处于挂起状态,GUI更新会保存在一个队列中,等JS引擎空闲时,立即执行

定时器线程

定时任务是通过定时器线程运行,他会在定时任务完成之后,通知事件触发线程,往任务队列里添加事件

异步HTTP请求线程

用来处理AJAX请求,当请求完成时,如果有回调函数,就会通知事件触发线程处理

事件触发线程

将满足触发条件的事件,添加到任务队列的末尾

EventLoop

主线程从任务队列中读取事件,这个过程是不断循环的,称为EventLoop(事件循环)
下图可以更好的帮助理解eventLoop,图中的宏任务和微任务下面会说明

微任务 宏任务

微任务(microtasks)

Promise Object.observe(监听对象变化) mutationObserve(一个类,监听DOM结构变化) postMessage(window对象之间用来通信)

宏任务(macrotasks)

script setTimeout setInterval setImmediate I/O UI rendering

异步任务分为宏任务和微任务,首先会执行script宏任务,然后执行完所有微任务之后才会执行宏任务
代码示例
需要注意的是,new Promise()里面的代码是一个参数,是同步执行的,then后面的代码才是异步执行

        console.log("start");
setTimeout(() => {
console.log("setTimeout1");
});
new Promise((resolve) => {
console.log("Promise1");
resolve();
}).then(() => {
console.log("then1");
new Promise((resolve) => {
resolve();
}).then(() => {
console.log("then2");
});
setTimeout(() => {
console.log("setTimeout2");
});
});
//结果start Promise1 then1 then2 setTimeout1 setTimeout2
        async function async1() {
console.log("asyncStart1");
await async2();
console.log("asyncEnd1");
}
async function async2() {
return Promise.resolve().then((res) => {
console.log("asyncPromise2");
});
}
console.log("start");
setTimeout(() => {
console.log("setTimeout");
}, 0);
async1();
new Promise((resolve) => {
console.log("promise1");
resolve();
}).then(() => {
console.log("promise2");
});
// 结果 start asyncStart1 promise1 asyncPromise2 promise2 asyncEnd1 setTimeout

js异步、事件循环(EventLoop)小结的更多相关文章

  1. 深入理解javascript中的事件循环event-loop

    前面的话 本文将详细介绍javascript中的事件循环event-loop 线程 javascript是单线程的语言,也就是说,同一个时间只能做一件事.而这个单线程的特性,与它的用途有关,作为浏览器 ...

  2. JS JavaScript事件循环机制

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

  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 的事件循环机制

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

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

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

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

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

  8. [浏览器事件循环] javaScript事件循环 EventLoop

    前言 Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理. 先熟悉基本概念 [堆Heap] 堆是一种数据结构 ...

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

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

  10. 前端中的事件循环eventloop机制

    我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的: console.log(1); setTimeout(function() { console. ...

随机推荐

  1. CyclicBarrier(栅栏)的用法详解及与countDownLatch用法区别

    CyclicBarrier适用于这样的情况:你希望创建一组任务,它们并行的执行工作,然后在进行下一步步骤之前等待,直至所有任务都完成,它使得所有的并行任务都将在删栏出列队,因此可以一致的向前移动. 当 ...

  2. istio kiali 亲和性调度

    一.节点调度 在开始 kiali 亲和性调度之前,先演示一个简单的例子介绍 pod 选择调度到指定 node: 节点打标 使用命令查看当前所有 k8s 节点: [root@k8s-master ~]# ...

  3. Sqoop(一)安装及基本使用

    Sqoop:     1.sqoop从数据库中导入数据到HDFS     2.SQOOP从数据库导入数据到hive     3.sqoop从hive中将数据导出到数据库   sqoop底层还是执行的m ...

  4. [从源码学设计]蚂蚁金服SOFARegistry 之 服务注册和操作日志

    [从源码学设计]蚂蚁金服SOFARegistry之服务注册和操作日志 目录 [从源码学设计]蚂蚁金服SOFARegistry之服务注册和操作日志 0x00 摘要 0x01 整体业务流程 1.1 服务注 ...

  5. 十八:SQL注入之堆叠及绕WAF

    堆叠查询注入 (双查询注入) stacked injections(堆叠注入)从名词的含义就可以看到是一堆的SQL语句一起执行,而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一 ...

  6. Desired_Capabilities配置

    appium服务器初始化参数 最全: https://github.com/appium/appium/blob/master/docs/cn/writing-running-appium/caps. ...

  7. Linux 安装JDK配置环境(rpm安装和压缩版安装)

    jdk安装 (rpm安装) jdk下载地址: https://www.oracle.com/cn/java/technologies/javase/javase-jdk8-downloads.html ...

  8. Java 使用URL类通过url下载网络资源

    主要用到的类 地址类: URL http类: HttpURLConnection 输入流: InputStream 输出流: FileOutputStream 上代码 package com.demo ...

  9. ORA-12560错误

    ora-12560错误是一个经典错误之一 下面我们分析一下这个错误: 产生这个错误的原因是什么呢? 1.oracle服务没有启动 Linux下查看$ps -ef | grep ora_ windows ...

  10. 【Linux】ethtool 用法

    ethtool命令用于获取以太网卡的配置信息,或者修改这些配置.这个命令比较复杂,功能特别多. 语法 ethtool [ -a | -c | -g | -i | -d | -k | -r | -S | ...