js异步编程-定时器
一、setTimeout
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
var timerId = setTimeout(func|code, delay);
- 传递一段代码
console.log(1);
setTimeout('console.log(2)',1000);
console.log(3);
// 1
// 3
// 2
- 传递一个函数
setTimeout(()=>{
console.log("hello word");
},1000)
3.setTimeout的第二个参数如果省略,则默认为0。
setTimeout(f)
// 等同于
setTimeout(f, 0)
- 还有一个需要注意的地方,如果回调函数是对象的方法,那么
setTimeout使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象。
var x= 1;
var obj = {
x: 2,
y: function () {
console.log(this.x);
}
};
setTimeout(obj.y, 1000) // 1
上面代码输出的是1,而不是2。因为当obj.y在1000毫秒后运行时,this所指向的已经不是obj了,而是全局环境。
为了防止出现这个问题,一种解决方法是将obj.y放入一个函数。
var x = 1;
var obj = {
x: 2,
y: function () {
console.log(this.x);
}
};
setTimeout(function () {
obj.y();
}, 1000);
// 2
上面代码中,obj.y放在一个匿名函数之中,这使得obj.y在obj的作用域执行,而不是在全局作用域内执行,所以能够显示正确的值。
- 除了前两个参数,
setTimeout还允许更多的参数。它们将依次传入推迟执行的函数(回调函数)。
setTimeout(function (a,b) {
console.log(a + b);
}, 1000, 1, 1);
//2
二、setInterval()
setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行
var div = document.getElementById('someDiv');
var opacity = 1;
div.style.opacity = opacity
var fader = setInterval(function () {
if (div.style.opacity >= 0)
div.style.opacity -= 0.1
else
div.style.opacity = opacity
}, 200);
定时器循环让someDiv的透明度逐渐变化
三、清除定时器
clearTimeout(),clearInterval()
setTimeout和setInterval函数,都返回一个整数值,表示计数器编号。将该整数传入clearTimeout和clearInterval函数,就可以取消对应的定时器。
var id1 = setTimeout(f, 1000);
var id2 = setInterval(f, 1000);
clearTimeout(id1);
clearInterval(id2);
四、防抖和节流
本质上是优化高频率执行代码的一种手段。
如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
- 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
一个经典的比喻:
想象每天上班大厦底下的电梯。把电梯完成一次运送,类比为一次函数的执行和响应
假设电梯有两种运行策略 debounce 和 throttle,超时设定为15秒,不考虑容量限制
电梯第一个人进来后,15秒后准时运送一次,这是节流
电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖.
防抖(Debounce): 防抖是指在事件触发后,等待一定的时间间隔,如果在这个时间间隔内没有再次触发事件,才执行对应的函数。如果事件在这个时间间隔内又触发了,那么等待时间会被重新计算。
应用场景: 在搜索框输入时,可以使用防抖来减少实时搜索请求的频率,只在用户停止输入一段时间后才触发搜索请求。
function debounce(func, delay) {
let timerId;
return function () {
let that = this //保存this
let args = arguments;//拿到event对象
clearTimeout(timerId);
timerId = setTimeout(() => {
func.apply(that, args)
}, delay)
}
}
function search() {
console.log('search...');
//搜索逻辑。。。
}
//简单实现,没有立即执行
const debounceSearch = debounce(search, 300)
节流(Throttle): 节流是指在一定时间间隔内,无论事件触发多少次,只会执行一次对应的函数。
应用场景: 在监听滚动事件时,可以使用节流来减少触发滚动事件处理函数的频率,以降低性能消耗。