执迷 执迷
首页
  • 技术分享

    • 小白都能看懂的闭包
    • GO-GMP模型
    • MySQL调优
    • centos7部署nacos
    • elasticserch
    • redis
  • 发布一个node插件

    • 发布一个npm包
    • 如何打包一个插件工具库
    • 打包工具的选择
  • JavaScript
  • ES6
  • CSS
  • 框架
  • Node
  • 服务
  • 其他
自我介绍
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

执迷

代码也是艺术
首页
  • 技术分享

    • 小白都能看懂的闭包
    • GO-GMP模型
    • MySQL调优
    • centos7部署nacos
    • elasticserch
    • redis
  • 发布一个node插件

    • 发布一个npm包
    • 如何打包一个插件工具库
    • 打包工具的选择
  • JavaScript
  • ES6
  • CSS
  • 框架
  • Node
  • 服务
  • 其他
自我介绍
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

    • JavaScript
    • 虚拟DOM
    • DOM和事件
    • ES6
    • 数组操作
    • JavaScript的深浅拷贝
    • JavaScript的执行
      • 执行
      • 定义宏任务和微任务
      • 宏任务和微任务的代码
      • 例子一
      • 例子二
    • JavaScript对象
    • JavaScript类型
    • JS概念
    • js设计模式
    • js深入浅出
    • Promise
    • this的指向
    • typescript
  • ES6

  • CSS

  • 框架

  • Node

  • 服务

  • 其他

  • 设计模式

  • web3

  • react

  • 学习笔记
  • JavaScript
执迷
2022-05-15
目录

JavaScript的执行

# JavaScript 的执行

首先一个 js 脚本本身对于浏览器而言就是一个宏任务,也是第一个宏任务,而处于其中的代码可能有 3 种:非异步代码、产生微任务的异步代码(promise 等)、产生宏任务的异步代码(settimeout、setinterval 等)。 我们知道宏任务处于一个队列中,应当先执行完一个宏任务才会执行下一个宏任务,所以在 js 脚本中,会先执行非异步代码,再执行微任务代码,最后执行宏任务代码。这时候我们进行到了下一个宏任务中,又按照这个顺序执行。

需要注意的是:微任务总是先于宏任务这个说法不准确,应该是处于同一级的情况下才能这么说。实际上微任务永远是宏任务的一部分,它处于一个大的宏任务内。

# 执行

  • 首先我们分析有多少个宏任务
  • 在每个宏任务中,分析有多少个微任务;
  • 根据调用次序,确定宏任务中的微任务执行次序;
  • 根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
  • 确定整个顺序。

# 定义宏任务和微任务

我们把宿主发起(浏览器api)的任务称为宏观任务,把 JavaScript 引擎发起的任务称为微观任务。

# 宏任务和微任务的代码

  • macro-task 大概包括:
    • script(整体代码)
    • setTimeout
    • setInterval
    • setImmediate
    • I/O
    • UI render
  • micro-task 大概包括:
    • process.nextTick
    • Promise
    • Async/Await(实际就是 promise)
    • MutationObserver(html5 新特性)

# 例子一

function sleep(duration) {
  return new Promise(function (resolve, reject) {
    console.log("b");
    setTimeout(resolve, duration);
  });
}
console.log("a");
sleep(5000).then(() => console.log("c"));
1
2
3
4
5
6
7
8

# 例子二

setTimeout(() => {
  console.log(1);
});
new Promise((res) => {
  console.log(3);
  res(2);
}).then((val) => {
  console.log(val);
});
console.log(4);
1
2
3
4
5
6
7
8
9
10

我们现在要实现一个红绿灯,把一个圆形 div 按照绿色 3 秒,黄色 1 秒,红色 2 秒循环改变背景色

function sleep(duration) {
  return new Promise(function (resolve) {
    setTimeout(resolve, duration);
  });
}
async function changeColor(duration, color) {
  document.getElementById("traffic-light").style.background = color;
  await sleep(duration);
}
async function main() {
  while (true) {
    await changeColor(3000, "green");
    await changeColor(1000, "yellow");
    await changeColor(2000, "red");
  }
}
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

参考

  • https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

  • https://juejin.cn/post/6962312899960242213

#JavaScript
上次更新: 2024/07/21, 21:46:04
JavaScript的深浅拷贝
JavaScript对象

← JavaScript的深浅拷贝 JavaScript对象→

最近更新
01
MySQL调优 原创
08-04
02
MySQL底层 原创
07-30
03
consul单台机器部署,注册外网服务健康检查 原创
07-30
更多文章>
Theme by Vdoing | Copyright © 2019-2024 执迷 | 闽ICP备2022018045号 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式