前言
有时候刷抖音看文章,时不时会碰到下面的一些字样,并且有些看着花里胡哨的,这里收集了他们的一些信息,合在一起记录一下,相信有用到的时候,一看就能分清楚,并分清他们
requestIdleCallback、requestAnimationFrame、setTimeout、setInterval、setImmediate、nextTick
requestAnimationFrame
动画帧回调函数 window.requestAnimationFrame() 方法会告诉浏览器你希望执行一个动画,它要求浏览器在下一次重绘之前,调用用户提供的回调函数,且仅仅回调一次,需要一直调用则需要继续调用 requestAnimationFrame 函数
//可以通过参数避免无限递归
let index = 0
function handler() {
idx++
if (idx < 6000) {
window.requestAnimationFrame(handler);
}
}
window.requestAnimationFrame(handler);
此方法一般用于做动画,平时操作用的不多,也不会参与后面的其他几个时机对比
requestIdleCallback
空闲调用函数 window.requestIdleCallback()
通过该方法插入一个函数,这个函数将在浏览器空闲时期被调用,这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。
const idle = window.requestIdleCallback((deadline) => {
console.log("requestIdleCallback");
});
//带有 options
const idle = window.requestIdleCallback((deadline) => {
console.log("requestIdleCallback");
}, {
timeout: 100,
});
//取消该事件
window.cancelIdleCallback(idle);
ps:由于是空闲执行,所以其优先级极低,甚至可以认为最低(如果不超时的话),优先级设置还在宏队列之后,但如果宏队列中间有等待时间,其也可能会提前执行的,虽然优先级低,但是如果此时等待时间没到,宏队列是没有实际任务加入的,也就是目前除了微队列、宏队列,只有空闲的这个队列有任务可以执行了
setTimeout、setInterval、setImmediate、nextTick
setTimeout、setInterval
这两个也是我们常用的时间函数了,分别是延迟一定时间调用、保持一定间隔时间调用(不会主动停止,需要自己取消),生成任务也就是很多人所说的宏队列中的任务,优先级比微队列的任务(promise、async)要低
//timeout 延迟500ms后执行,执行完毕后结束,可以提前取消
const timeout = setTimeout(() => {}, 500);
clearTimeout(timeout);
//interval每间隔 500ms 后执行,直到主动取消
const interval = setInterval(() => {}, 500);
clearInterval(interval);
ps:虽然也有使用 setInterval 做动画的,但是由于其特性,会被动暂停,也容易卡事件导致卡顿,可能更适合做一些简单滚屏的操作
setImmediate(nodeJS环境使用)
setImmediate 在IO事件回调之后立即执行的回调函数,其优先级基本在 setTimeout 前后,一般不参与比较
//没有等待函数
setImmediate(() => {
console.log('This will be executed in the next iteration of the event loop');
});
在浏览器环境中,可以使用window.setTimeout 来实现类似的效果。然而,setImmediate 并不是标准的 Web API,在 nodeJS 环境使用,所以在跨浏览器开发时,使用 setTimeout 来代替 setImmediate。
nextTick
浏览器 nextTick nextTick 通常会在当前微任务队列中的其他任务执行完毕后(可以理解为微任务队列的末尾),立即执行回调函数,优先级比较低,和 nodejs 有些不一样(vue 中直接 this.$nextTick,React 需要 从 process 中导出 nextTick,然后使用 nextTick)
nodejs的 process.nextTick Node.js 中的 process.nextTick 具有更高的优先级,会在微任务队列中的其他任务之前执行,回调函数会在当前执行栈清空后立即执行,执行优先级非常高,和浏览器的有些不一样
process.nextTick(() => {
console.log("process.nextTick");
});
requestIdleCallback、setTimeout、nextTick 对比
这边就是用 requestIdleCallback、setTimeout、setImmediate、process.nextTick 他们是哪个做一下简单的对比,分别打印
下面是浏览器的执行环境,可以看出浏览器的 nextTick 执行时机在 promise、setTimeout之间
import {nextTick} from "process"
const func1 = async () => {
console.log(1)
await func2()
}
const func2 = async () => {
console.log(2);
};
const func3 = async () => {
console.log(3);
};
const main = async () => {
window.requestIdleCallback((deadline) => {
console.log("requestIdleCallback");
});
setTimeout(() => {
console.log("setTimeout");
}, 0);
nextTick(() => {
console.log("nextTick");
});
await func1()
await func3()
};
main()
1
2
3
nextTick
setTimeout
requestIdleCallback
下面使用 nodejs 执行环境,发现 process.nextTick 的执行时机已然不同(可以搭配循环测试一下, 这里不作为重点了)
const func1 = async () => {
console.log(1)
await func2()
}
const func2 = async () => {
console.log(2);
};
const func3 = async () => {
console.log(3);
};
const main = async () => {
globalThis.requestIdleCallback((deadline) => {
console.log("requestIdleCallback");
});
setTimeout(() => {
console.log("setTimeout");
}, 0);
process.nextTick(() => {
console.log("process.nextTick");
});
await func1()
await func3()
};
main()
// vscode 的 Code Runner 执行结果
打印结果如下所示
1
2
process.nextTick
3
setTimeout
requestIdleCallback