chrome事件循环的自问自答

目录

1. 宏任务有哪些?

  • 事件回调 (js调用的 click box.click()
  • XHR或网络请求回调
  • 定时器的回调
  • I/O回调
  • history相关回调
  • MessageChannel的message回调

在合适时机,这些宏任务会被推入宏任务队列;每一次事件循环会从宏任务队列中取一个任务执行。

history.back回调:

<button id='box'>forward</button>
<button id='box2'>back</button> <script>
var box = document.getElementById('box');
var box2 = document.getElementById('box2');
box.addEventListener('click',()=>{
history.pushState('state',null,'?page=1');
}) window.addEventListener('popstate',function (ev) {
console.log('popstate');
})
box2.addEventListener('click',()=>{
history.back();
setTimeout(()=>{
console.log('timeout');
})
})
</script>

MessageChannel的message回调

<button id='btn'>btn</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
var channel = new MessageChannel();
channel.port1.onmessage = function onmessage1 (){
console.log('postMessage')
Promise.resolve().then(function promise1 (){
console.log('promise')
})
};
setTimeout(function setTimeout2(){
console.log('setTimeout')
}, 0)
channel.port2.postMessage(0);
};
</script>

I/O回调

<input type="file" id="input" multiple>
<script>
input.addEventListener('change', function () {
var file = input.files[0]
var reader = new FileReader()
reader.onload = function (ev) {
console.log(reader.result);
}
reader.readAsArrayBuffer(file)
})
</script>

2. 微任务有哪些?

MutationObserver的回调、Promise的then catch finally回调、queueMicrotask.

在合适时机,这些微任务会被推入微任务队列;每一次事件循环会从微任务队列中取所有任务并执行。

Promise和queueMicrotask不支持IE, MutationObserver支持IE11;

MutationObserver例子:

下面的代码中box.textContent = 1的位置不同,代码的执行顺序就不同以验证MutationObserver为微任务。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
const mo = new MutationObserver(function (mutations) {
console.log('mutations')
})
mo.observe(box, {
childList: true
})
box.onclick = function () {
// box.textContent = 1;
Promise.resolve().then(()=>{
console.log(333)
})
box.textContent = 1;
};
</script>

以下是使用`queueMicrotask`方法手动添加微任务的例子,可以不会对更高优先级的代码运行造成干扰。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
queueMicrotask(()=>{
console.log(121212)
})
console.log(333)
};
</script>

3. dom渲染是事件循环的一部分么?

从规范的角度来看,DOM渲染是事件循环的一部分,可以将其视为一种渲染任务。

如果宏任务或者微任务中发生了dom修改,因为一个渲染帧的时间可能远大于事件循环周期,所以不一定在本次事件循环会执行渲染任务。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
setTimeout(function setTimeout17 () {
box.textContent = 1;
}, 0)
setTimeout(function setTimeout18 () {
box.textContent = 2;
}, 0)
};
</script>

下图是上面的代码的执行流程,两个setTimeout的回调执行代表两次事件循环,在其后面出现了一个新的Task,仅执行了一次布局(layout)和绘制(paint);

4. requestAnimationFrame的回调是宏任务还是微任务?

requestAnimationFrame的回调函数会在浏览器在下一帧渲染之前执行, 既不是宏任务,也不是微任务, 从规范上看是事件循环的一部分,从下图可以看到一个task下包含了requestAnimationFrame,layout paint, 可将其归类于渲染任务的一个可选步骤。

<div id='box'>0</div>
<script>
const box = document.getElementById('box');
box.onclick = function () {
setTimeout(function setTimeout17 () {
box.textContent = 1;
requestAnimationFrame(()=>{
console.log(111)
Promise.resolve().then(()=>{
console.log(333)
})
})
}, 0)
setTimeout(function setTimeout18 () {
box.textContent = 2;
requestAnimationFrame(()=>{
console.log(222)
})
}, 0)
};
</script>

上述代码中添加了两个requestAnimationFrame,可以看到两者在一个Task内顺序执行;并且回调中的微任务也在这个Task内执行;

5. requestIdleCallback的回调是宏任务还是微任务?

requestIdleCallback是事件循环的一部分,从图中可以看到,requestIdleCallback的回调是一个特殊的任务,这个函数的回调会在浏览器空闲时期被调用,所以不是每次循环都会执行该任务。

<button id='btn'>btn</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
requestIdleCallback(function () {
btn.innerHTML = "sdfsdfs"
setTimeout(()=>{
console.log(3)
},0)
Promise.resolve().then(()=>{
console.log(4)
})
})
};
</script>

该任务的优先级比较低,多个平行声明的requestIdleCallback会拆开成单一的task, 两个连续task之间甚至会被内部的setTimeout插足。

for (let i = 0; i < 10; i++) {
requestIdleCallback(() => {
console.log('idle', Date.now() - a)
setTimeout(()=>{
console.log(12121)
})
})
}

6. 事件循环图例

chrome事件循环的自问自答的更多相关文章

  1. nodejs的事件循环1

    JavaScript的学习零散而庞杂,因此很多时候我们学到了一些东西,但是却没办法感受到自己的进步,甚至过了不久,就把学到的东西给忘了.为了解决自己的这个困扰,在学习的过程中,我一直试图在寻找一条核心 ...

  2. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  3. js事件循环

    之前有看过一些事件循环的博客,不过一阵子没看就发现自己忘光了,所以决定来自己写一个博客总结下! 首先,我们来解释下事件循环是个什么东西: 就我们所知,浏览器的js是单线程的,也就是说,在同一时刻,最多 ...

  4. 深入理解 JavaScript 事件循环(二)— task and microtask

    引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...

  5. 浏览器与Node的事件循环(Event Loop)有何区别?

    前言 本文我们将会介绍 JS 实现异步的原理,并且了解了在浏览器和 Node 中 Event Loop 其实是不相同的. 一.线程与进程 1. 概念 我们经常说 JS 是单线程执行的,指的是一个进程里 ...

  6. 详解JavaScript中的Event Loop(事件循环)机制

    前言 我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言.这是由其最初的用途来决定的:与浏览器交互. 单线程意味着,javascript代码在执行的任何时候,都只有一个主线程 ...

  7. [译] 深入理解 JavaScript 事件循环(二)— task and microtask

    引言 microtask 这一名词是 JS 中比较新的概念,几乎所有人都是在学习 ES6 的 Promise 时才接触这一新概念,我也不例外.当我刚开始学习 Promise 的时候,对其中回调函数的执 ...

  8. 理解js事件循环(event loop)

    队列:先进先出 栈:后进先出 javascript的Event Loop 和 Node.js的Event Loop 区别: js(运行在浏览器),有主线程.异步任务队列的概念: node.js使用li ...

  9. css自问自答(二)

    css自问自答(二) 7.掌握定位的一些属性 position 和 display 属性,以及如何浮动(float)和清除(clear)元素,z-index属性 三个属性控制: position 属性 ...

  10. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

随机推荐

  1. PowerBI(一) : 如何将powerBI报表嵌入内部web应用程序?

    最近做了一个PowerBI报表嵌入内部web应用系统的项目,分享一下主要步骤以及踩坑记录. 微软官网完整教程这里:https://learn.microsoft.com/zh-cn/power-bi/ ...

  2. oss/obs对象存储上传图片,在浏览器输入地址却是下载图片。不能直接在浏览器上查看。

    1.问题oss/obs对象存储上传图片获取链接地址后,在浏览器输入地址却是下载.不能直接在浏览器上面浏览图片信息.2.解决上传文件的时候需要设置:content-type类型,需要指示浏览器这是什么类 ...

  3. vue本地开发配置及项目部署

    一,  二,本地模拟配置代理,请求qq音乐的接口数据  三,axios请求头封装               参考http://www.axios-js.com/zh-cn/docs/#%E4%BB% ...

  4. [Pytorch框架] 5.1 kaggle介绍

    文章目录 5.1 kaggle介绍 5.1.1 Kaggle 平台简介 比赛介绍 5.1.2 Kaggle板块介绍 Data Rules Team Kernels Discussion Leaderb ...

  5. Prism Sample 29-InvokeCommandAction

    一下子跳到29,不是我的错,应该是新版本中去掉了一些过重的功能,案例就也去掉了,所以不是我的错. 本例是演示行为转命令的,事实上前面已经用到了. xmlns:i="http://schema ...

  6. 试用「ChatGPT」几周之后

    冷静下来,不吹不黑. 01 最近半年,互联网一款现象级的应用诞生:「ChatGPT」: 其火爆的程度,不输前面的羊了个羊: 最初了解到ChatGPT还是春节的时候,但那时网上的测评还没引起足够的好奇心 ...

  7. selenium 执行js脚本

    使用 selenium 直接在当前页面中进行js交互 使用selenium 执行 Js 脚本 要使用 js 首先要知道 js 怎么用,现在举个简单得例子,就用12306举例子, 它的首页日期选择框是只 ...

  8. Pillow模块——生成随机验证码

    urls.py path('get_code/',views.get_code), views.py中 from PIL import Image,ImageFont,ImageDraw " ...

  9. 2022-03-05:不相交的线。 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直

    2022-03-05:不相交的线. 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数. 现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直 ...

  10. 2021-05-08:给定两个非负数组x和hp,长度都是N,再给定一个正数range。x有序,x[i]表示i号怪兽在x轴上的位置;hp[i]表示i号怪兽的血量 。range表示法师如果站在x位置,用A

    2021-05-08:给定两个非负数组x和hp,长度都是N,再给定一个正数range.x有序,x[i]表示i号怪兽在x轴上的位置:hp[i]表示i号怪兽的血量 .range表示法师如果站在x位置,用A ...