js 在浏览器中的event loop事件队列
前言
以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意。
都说js是单线程的,不过它本身其实不是单线程,但是在浏览器中执行时只分配一个线程进行执行。
所以说js执行是单线程的,一次只能进行一项任务,就是一件任务一件任务做,做完一件做下一件。
认识一个栈两个队列
一个调用栈Stack。
一个宏队列,macrotask,也叫tasks。
一个微队列,microtask,也叫jobs。
执行过程
js就是执行全局Script同步代码,这中间碰到一些异步任务先加进对应的队列。
做完之后,调用栈就为空了。
然后将队列(先微队列后宏队列)里面的首个任务提到调用栈来做,一件一件做完直到队列中的任务都做完。
总结就是,先做同步的任务,再做微队列的任务,再做宏队列的任务。
异步任务怎么分配
这些异步任务包括但不限于:
以下分配给宏队列:
setTimeout
setInterval
requestAnimationFrame
I/O
UI rendering
以下分配给微队列:
Promise
Object.observe
MutationObserver
常见的宏队列:setTimeout,常见的微队列:Promise。
简单例子
    console.log("同步任务1");
    setTimeout(() => {
      console.log("宏任务");
    });
    new Promise((resolve, reject) => {
      console.log("同步任务2");
      resolve("微任务");
    }).then((data) => {
      console.log(data);
    });
    console.log("同步任务3");
结果是(按标号加任务,按箭头执行):


需要注意的是Promise的第一层没有执行回调之前是同步的,也就是上面的同步任务2。
难一点的例子
    console.log("同步任务1");
    console.log("同步任务2");
    new Promise((resolve, reject) => {
      console.log("同步任务3");
      setTimeout(() => {
        console.log("宏任务1");
        Promise.resolve()
          .then(() => {
            console.log("微任务5");
          })
          .then(() => {
            console.log("微任务6");
          });
      });
      resolve("微任务1");
    })
      .then((data) => {
        console.log(data);
        return "微任务3";
      })
      .then((data) => {
        console.log(data);
      });
    setTimeout(() => {
      console.log("宏任务2");
    }, 0);
    new Promise((resolve, reject) => {
      resolve("微任务2");
    })
      .then((data, resolve) => {
        console.log(data);
        return "微任务4";
      })
      .then((data) => {
        console.log(data);
      });
    console.log("同步任务4");
如何看呢,先看第一层,红色代表同步,绿色微任务,蓝色宏任务。
我们会把同步任务执行完,然后看见微任务有俩,宏任务也有俩。
本来的执行顺序可能是这样(我这里按照序号来表达顺序了,请和简单例子区分开来):

但是没那么顺利,执行到标号6时不一样了。
因为微任务执行过程中可能会产生新的微任务。
上面的微任务1执行完会把微任务3加在微任务2后面,也就是微任务2执行完也轮不到宏任务,会继续执行新的微任务直到微任务队列暂时为空。
所以接下来会按照加入队列的顺序执行完四个微任务,这时候发现没有新的微任务产生,才开始执行宏任务:

但是需要注意的是,上面执行到标号5时又不一样了,宏任务一执行后又产生了新的微任务,所以宏任务两个并没有顺利连续执行,而是被插入的微任务拦住了。
(要记住微任务与宏任务队列都存在时一定是微任务先执行完再来执行宏任务,即使是宏任务执行产生的微任务也同理)

所以最后的答案,如果存在不理解的,可以在认真回顾一下上文:

js 在浏览器中的event loop事件队列的更多相关文章
- 浏览器中的 Event Loop
		
当我们执行 JS 代码的时候其实就是往执行栈中放入函数,那么遇到异步代码的时候该怎么办?其实当遇到异步的代码时,会被挂起并在需要执行的时候加入到 Task(有多种 Task) 队列中.一旦执行栈为空, ...
 - js的事件循环(Event Loop)
		
(本文从掘金小册整理) 首先介绍一下几个概念 进程与线程 相信大家经常会听到 JS 是单线程执行的,但是你是否疑惑过什么是线程? 讲到线程,那么肯定也得说一下进程.本质上来说,两个名词都是 CPU 工 ...
 - 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?
		
https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...
 - [NodeJs系列][译]理解NodeJs中的Event Loop、Timers以及process.nextTick()
		
译者注: 为什么要翻译?其实在翻译这篇文章前,笔者有Google了一下中文翻译,看的不是很明白,所以才有自己翻译的打算,当然能力有限,文中或有错漏,欢迎指正. 文末会有几个小问题,大家不妨一起思考一下 ...
 - Node.js的事件轮询Event Loop原理
		
Node.js的事件轮询Event Loop原理解释 事件轮询主要是针对事件队列进行轮询,事件生产者将事件排队放入队列中,队列另外一端有一个线程称为事件消费者会不断查询队列中是否有事件,如果有事件,就 ...
 - 不要在nodejs中阻塞event loop
		
目录 简介 event loop和worker pool event loop和worker pool中的queue 阻塞event loop event loop的时间复杂度 Event Loop中 ...
 - Elasticsearch.js 发布 —— 在Node.js和浏览器中调用Elasticsearch(1)
		
继PHP.Ruby.Python和Perl之后,Elasticsearch最近发布了Elasticsearch.js,Elasticsearch的JavaScript客户端库.可以在Node.js和浏 ...
 - Elasticsearch.js 发布 —— 在Node.js和浏览器中调用Elasticsearch
		
继PHP.Ruby.Python和Perl之后,Elasticsearch最近发布了Elasticsearch.js,Elasticsearch的JavaScript客户端库.可以在Node.js和浏 ...
 - 浏览器和Node 中的Event Loop
		
前言 js与生俱来的就是单线程无阻塞的脚本语言. 作为单线程语言,js代码执行时都只有一个主线程执行任务. 无阻塞的实现依赖于我们要谈的事件循环.eventloop的规范是真的苦涩难懂,仅仅要理解的话 ...
 
随机推荐
- 【C++基础教程】第四课
			
上次的课后练习 第1题输出: 第二题输出:1 第三题: #include<iostream> #include<cmath> using namespace std; int ...
 - php处理url的rawurlencode:可处理空格加号
			
(PHP 4, PHP 5, PHP 7) rawurlencode - 按照 RFC 3986 对 URL 进行编码 返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号( ...
 - jenkins自动构建前端项目(window,vue)
			
我们把一个多人协作的vue前端项目发布服务器,一般要经过以下步骤: git更新最新的代码 构建项目 把构建后的代码上传到服务器 如果用jenkins来构建的话,只需要点击一次构建按钮,就可以自动完成以 ...
 - Dubbo 学习(二)服务注册与发现
			
在上一篇中我们提到,dubbo官网上推荐使用ZooKeeper作为注册中心.那么今天我们就通过代码来实践一番,看看一个dubbo的服务消费者如果找到通过ZooKeeper暴露自己的dubbo服务提供者 ...
 - 鸿蒙内核源码分析(重定位篇) | 与国际接轨的对外部发言人 | 百篇博客分析OpenHarmony源码 | v55.01
			
百篇博客系列篇.本篇为: v55.xx 鸿蒙内核源码分析(重定位篇) | 与国际接轨的对外部发言人 | 51.c.h.o 加载运行相关篇为: v51.xx 鸿蒙内核源码分析(ELF格式篇) | 应用程 ...
 - P5488-差分与前缀和【NTT,生成函数】
			
正题 题目链接:https://www.luogu.com.cn/problem/P5488 题目大意 求一个长度为$n$的序列的$k$阶差分/前缀和. 解题思路 先考虑前缀和怎么做 搞出来生成函数就 ...
 - P4233-射命丸文的笔记【NTT,多项式求逆】
			
正题 题目链接:https://www.luogu.com.cn/problem/P4233 题目大意 随机选择一条有哈密顿回路的\(n\)个点的竞赛图,求选出图的哈密顿回路的期望个数. 对于每个\( ...
 - YbtOJ#853-平面标记【整体二分,凸壳】
			
正题 题目链接:http://www.ybtoj.com.cn/contest/119/problem/3 题目大意 给出\(n\)个点\((x_i,y_i)\),\(m\)次给出\((k_i,a_i ...
 - disruptor笔记之五:事件消费实战
			
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
 - mybatis本地缓存&分布式缓存干货分享
			
前言:干货记录学习mybatis实际开发中缓存的使用. 环境: springboot2.X + mybatis3.x Mybatis是一款持久层框架,它提供了一级缓存和二级缓存. 名词解释 一级缓存( ...