事件循环和raf

事件循环和raf

一. 为什么需要事件循环

由于js是单线程执行的,所以设计了事件循环用于处理异步函数

二. 事件循环介绍

1. 队列

事件循环中至少需要两个队列 – 宏任务队列微任务队列,可能有其他不同的队列,不同浏览器有不同的方案

其中宏任务队列主要包含点击事件计时器网络请求的回调
微任务队列主要包含Promiseasync中的await后的语句

2. 队列机制

每个循环中,会先判断微任务队列是否为空,不为空就之行微任务队列直至队列空,然后从宏任务队列中取出一个任务执行,如果修改了DOM,会触发页面渲染

因此可以说: 队列优先处理微任务

Alt text

来看题😀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async function async1() {
console.log('a');
await async2();
console.log('b');
}

async function async2() {
console.log('c')
}

console.log('d')
async1();

setTimeout(()=> {
console.log('e')
},0)

new Promise((resolve, reject) => {
console.log('f')
resolve()
}).then(()=> {
console.log('g')
})

三. 来看渲染😵

Alt text

前面说了setTimeout是宏任务,那结合事件队列的知识,setTimeout函数就需要等待之前的所有微任务和宏任务执行完才能执行,那就导致了一个问题: setTimeout函数计时是不准的!

还要要知道浏览器的默认渲染频率是固定的,大概为每秒60帧

Alt text

所以用setTimeout整的动画函数执行频率会不同,可能每次渲染中执行的函数数量不同,看起来就会有抖动,还没完!

如果事件执行时间过长,还会导致丢帧,因为事件循环和渲染是两个独立的进程!js还是个单线程,两头顾不上

Alt text

因此,js开发者们有了一个天才的点子,raf动画

四. RAF

RequestAnimationFrame 是一个在现代 Web 开发中广泛使用的 JavaScript 方法,它用于在浏览器的下一次重绘之前执行动画帧,以提供更平滑的动画效果。这种方法通常用于创建用 HTML、CSS 和 JavaScript 编写的交互式网页动画。

Alt text

1
2
3
4
5
6
7
8
9
10
function animate() {
positionX += speed;
if (positionX > window.innerWidth) {
positionX = -animatedElement.clientWidth;
}
Element.style.transform = `translateX(${positionX}px)`;
requestAnimationFrame(animate);
}

animate();

事件循环和raf
http://baidu.com/2023/09/16/eventloop&raf/
作者
KB
发布于
2023年9月16日
许可协议