首先观察一下下面两组代码区别在哪里?
第一组代码
setInterval(() => {
// 1.5s 的同步逻辑
}, 1000);
第二组代码
function fn() {
setTimeout(() => {
// 1.5s 的同步逻辑
fn();
}, 1000);
}
fn();
两组代码都有定时功能,看起来也都是每隔1s执行一次任务(同步逻辑),实际上这两组代码的1s间隔代表的意义不一样;
这里通过几组图来表示:
1. 第一组代码会将任务每隔1秒就加入任务队列
function sleep(sleepTime) {
const start = Date.now();
while(Date.now() - start < sleepTime) {}
}
- 如果执行一次任务需要0.3秒,第一组代码中,任务之间的真正间隔是0.7秒
let now = Date.now();
setInterval(() => {
console.log(`任务间隔:${Date.now() - now}`);
sleep(300);
now = Date.now();
}, 1000);
- 如果执行一次任务需要1秒,第一组代码中,任务之间的真正间隔是0秒
let now = Date.now();
setInterval(() => {
console.log(`任务间隔:${Date.now() - now}`);
sleep(1000);
now = Date.now();
}, 1000);
- 如果执行一次任务需要1.5秒(超过定时器规定的1秒),第一组代码中,任务之间的真正间隔仍然是0秒
let now = Date.now();
setInterval(() => {
console.log(`任务间隔:${Date.now() - now}`);
sleep(1500);
now = Date.now();
}, 1000);
2. 第二组代码会在调用fn()后立即执行一个定时器,该定时器将在1秒后触发回调函数,实现了真正意义上的定时
function sleep(sleepTime) {
const start = Date.now();
while(Date.now() - start < sleepTime) {}
}
- 执行一次任务0.3秒
let now = Date.now();
function fn() {
setTimeout(() => {
console.log(`任务间隔:${Date.now() - now}`);
sleep(300);
now = Date.now();
fn();
}, 1000);
}
fn();
- 执行一次任务1.5秒
let now = Date.now();
function fn() {
setTimeout(() => {
console.log(`任务间隔:${Date.now() - now}`);
sleep(1500);
now = Date.now();
fn();
}, 1000);
}
fn();