在实际开发中,我们可能会延时执行某一个操作,比如主页加载完之后,延时 n
秒弹出广告,这个时候我们就需要用到延时函数啦。
语法形式:
setTimeout(callback, delay);
语法解读:
callback
:回调函数,延迟时间结束之后调用的函数delay
:延迟时间,单位ms
console.log("登陆中, 请稍后...");
setTimeout(function(){
console.log("欢迎木子李!");
}, 2000);
console.log("...");
登陆中, 请稍后...
...
欢迎木子李!
注意:延时函数为异步操作,不会阻塞线程。
在延时的过程中,有时因为某种情况,不执行延时函数了,那么我们就需要取消延时,语法如下:
clearTimeout(t)
代码示例:
console.log("登陆中, 请稍后...");
// 定义变量记录延时函数
var t = setTimeout(function(){
console.log("欢迎木子李!");
}, 5000);
console.log("...");
// 清除延时函数
clearTimeout(t);
// 登陆中, 请稍后...
// ...
在实际开发中,如果我们需要每隔一段时间就做某个事情的时候,我们可以使用定时器,比如在做倒计时功能的时候就可以用到定时器函数。
语法形式:
setInterval(callback, interval);
语法解读:
callback
:回调函数,每隔指定时间都会执行一次回调函数interval
:时间间隔,单位ms
var count = 10;
setInterval(function() {
console.log(--count);
}, 1000);
上述代码,每隔1秒钟就会让 count
变量自减 1
并输出。
清除定时器和清除延时函数一样,只需使用 clearInterval()
函数即可。
var count = 5;
// 定义变量存储定时器
var t = setInterval(function() {
if(count == 0) {
console.log("时间到!");
// 清除定时器
clearInterval(t);
return;
}
console.log(--count);
}, 1000);
思路:
-
时间差计算(
ms
):目标时间 - 当前时间 -
将时间差(
ns
)转换为天、时、分、秒:let day = Math.floor(ms / 1000 / 60 / 60 / 24); let hours = Math.floor(ms / 1000 / 60 / 60 % 24); let minutes = Math.floor(ms / 1000 / 60 % 60); let seconds = Math.floor(ms / 1000 % 60);
比如,呈现一个距离2023年国庆的倒计时功能:
function countdown(targetDate, callback) {
var d, ms, t, day, hours, minutes, seconds;
var format = (v) => v.toString().padStart(2, '0');
t = setInterval(function () {
d = new Date();
ms = targetDate - d;
if (ms > 0) {
day = format(Math.floor(ms / 1000 / 60 / 60 / 24));
hours = format(Math.floor((ms / 1000 / 60 / 60) % 24));
minutes = format(Math.floor((ms / 1000 / 60) % 60));
seconds = format(Math.floor((ms / 1000) % 60));
callback({ day, hours, minutes, seconds });
} else {
clearInterval(t);
}
}, 1000);
}
countdown(new Date('2023/10/01'), function (r) {
console.log(
`距离2023年国庆还有${r.day}天${r.hours}时${r.minutes}分${r.seconds}秒`
);
});
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
比如搜索功能,在搜索内容变化后就触发搜索事件请求接口,有时候我们输的内容很长,在没有输完的时候就触发了事件,这样就造成了很多无用的请求,这时候就需要用到防抖函数,来让其在搜索内容变化后的指定时间内如果没有再更改才发起请求。
思路:每次触发事件时都取消之前的延时调用方法
function debounce(callback, delay = 500) {
let t = null;
return function (...args) {
clearTimeout(t);
t = setTimeout(() => {
callback.apply(this, args);
}, delay);
}
}
使用:
const input = document.querySelector("input");
input.oninput = debounce(function () {
console.log('__Search__');
});
高频事件触发,在n秒内只会执行一次,所以节流会稀释函数的执行频率。就比如老板给你布置了一个任务,在指定时间内你只需要专心完成老板布置的任务即可,期间如果产品经理过来给你派发任务的时候,你可以直接忽略(当然实际情况是作为苦逼的程序猿来讲忽略是不可能的)。
函数节流的应用场景一般是 onresize
,onscroll
等这些频繁触发的函数,比如你想获取滚动条的位置,然后执行下一步动作。如果监听后执行的是DOM操作,这样的频繁触发执行,可能会影响到浏览器性能,甚至会将浏览器卡崩,所以我们可以规定他多少秒执行一次。
思路:每次触发事件时都判断当前是否有等待执行的延时函数
function throttle(callback, delay = 500) {
// 1. 设置一个开关
let isOn = true;
return function (...args) {
// 2. 如果当前正在执行某个任务,则忽略
if (!isOn) return;
// 3. 更新开关状态
isOn = false;
// 4. 启用定时器
setTimeout(() => {
callback.apply(this, args);
isOn = true;
}, delay);
}
}
使用:
window.onresize = throttle(function (event) {
console.log(event.target.innerWidth, event.target.innerHeight);
});