js异步、事件循环(EventLoop)小结
单线程
众所周知,JS是单线程的语言,之所以是单线程,用一句烂大街的话就是,如果两个线程同时操作一个DOM节点,那么该以哪个为准呢,虽然多线程也有办法解决,但是js毕竟是浏览器脚本语言,不需要那么复杂
但是单线程遇到多个任务,需要排队执行,如果遇到定时器任务或者ajax请求等等,那会严重影响用户体验,于是将异步任务暂时挂起,先运行后面的任务,等异步操作返回了结果,再来执行
所以把任务分为两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous),同步任务是指在主线程上排队的任务,只有前一个任务执行完毕,才会执行后面的任务,异步任务是指不进入主线程,而是进入任务队列(task queue),当任务队列通知主线程某一个异步任务可以执行的时候,才会进入主线程执行。
同步 异步执行机制
2 主线程之外,还有一个任务队列(task queue)
3 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,里面的异步任务就会结束等待状态,进入执行栈,开始执行
4 主线程会不断的重复上面的三部内容
进程
程序运行的实例,同一个程序可以产生多个进程,一个进程可以包含多个线程
线程
操作系统能够进行运算调度的最小单位,一个只能执行一个任务,有自己的调用栈,寄存器环境,同一个进程的线程共享进程资源
浏览器进程: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)小结的更多相关文章
- 深入理解javascript中的事件循环event-loop
前面的话 本文将详细介绍javascript中的事件循环event-loop 线程 javascript是单线程的语言,也就是说,同一个时间只能做一件事.而这个单线程的特性,与它的用途有关,作为浏览器 ...
- JS JavaScript事件循环机制
区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...
- Node.js:事件循环
ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...
- Node.js 的事件循环机制
目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...
- 浏览器中 JS 的事件循环机制
目录 事件循环机制 宏任务与微任务 实例分析 参考 1.事件循环机制 浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图). 第一步:主线程(JS引擎线程)中执行 ...
- js的事件循环绑定和jQuery的隐式迭代
js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...
- js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)
javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...
- [浏览器事件循环] javaScript事件循环 EventLoop
前言 Event Loop即事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理. 先熟悉基本概念 [堆Heap] 堆是一种数据结构 ...
- JavaScript之JS单线程|事件循环|事件队列|执行栈
本博文基于知乎"JavaScript作用域问题?"一问,而引起了对JavaScript事件循环和单线程等概念与实践上的研究.深入理解. 一.概念 0.关键词:JavaScript单 ...
- 前端中的事件循环eventloop机制
我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的: console.log(1); setTimeout(function() { console. ...
随机推荐
- js实现页面消息滚动效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 记一次由于引用第三方服务导致的GC overhead limit exceeded异常
最近笔者遇到一个问题 监控平台忽然告警 GC overhead limit exceeded 这个异常 第一反应估计是堆溢出了.于是各种各种jmap jstack下载堆栈文件和堆日志文件. 以下是 ...
- Spring Boot 2.x基础教程:实现文件上传
文件上传的功能实现是我们做Web应用时候最为常见的应用场景,比如:实现头像的上传,Excel文件数据的导入等功能,都需要我们先实现文件的上传,然后再做图片的裁剪,excel数据的解析入库等后续操作. ...
- YGGL.sql
(将表复制粘贴至记事本,再用source命令导入到数据库中) CREATE TABLE `departments` ( `部门编号` char(3) NOT NULL COMMENT '部门编号', ...
- spring cache 学习 —— @Cacheable 使用详解
1. 功能说明 @Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的.也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方 ...
- #2020征文-开发板# 用鸿蒙开发AI应用(二)系统篇
目录: 前言 安装虚拟机 安装 Ubuntu 设置共享文件夹 前言上回说到,我们在一块 HarmonyOS HiSpark AI Camera 开发板,并将其硬件做了一下解读和组装.要在其上编译鸿蒙系 ...
- 【剑指 Offer】10-II.青蛙跳台阶问题
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008, ...
- 【Flutter】容器类组件之装饰容器
前言 DecoratedBox可以在其子组件绘制前后绘制一些装饰,例如背景,边框,渐变等. 接口描述 const DecoratedBox({ Key key, // 代表要绘制的装饰 @requir ...
- LAN-SHARE 使用教程
Description: 我的个人项目 LAN-Share 的使用教程:局域网内文件分享工具 LAN-Share 是一个基于 Node.js 的用于局域网内文件分享的工具,易于配置与部署. 项目地址: ...
- 【JS学习】String基础方法
前言:本博客系列为学习后盾人js教程过程中的记录与产出,如果对你有帮助,欢迎关注,点赞,分享.不足之处也欢迎指正,作者会积极思考与改正. 目录 定义: 字符串的连接: 标签模板的使用: 字符串的基本方 ...