setTimeout和setInterval

一,setTimeoutsetInterval介绍

1.很多人容易把setTimeoutsetInterval理解成线程概念,其实不然,js是单线程的,setTimeoutsetInterval的计时虽然运行在浏览器内核的定时触发器线程上,但真正的回调函数依然被添加到事件队列,在js引擎线程中执行。

2.setTimeoutsetInterval的作用简单来说就是将一些操作延时执行。

二,setTimeout

1.setTimeout(fn,[interval]):用来指定某个函数或字符串在指定的毫秒数之后执行。该函数return一个值,表示定时器编号。interval的缺省值为0

2.HTML5标准规定,setTimeout的最短时间间隔是4ms,当设置时间小于4ms时都会自动调整成4ms

2.为了兼容IE9,可以使用IIFE或者隐式调用向函数传递参数。

setTimeout((function(a,b){console.log(a+b)})(1,2),1000)
function add(a,b)
{
	return a+b
}
setTimeout(function(){add(1,2)},1000)

三,setInterval

1.setInterval(fn,[interval]):用来指定某个函数或字符串在指定的间隔内不停的执行。

{
	setInterval(function(){console.log(a+b)},1000)
}

2.JavaScript引擎规定:当使用setInterval()时,仅当队列中没有该定时器的任何其他代码实例时,才将回调函数添加到队列中。这确保了定时器代码加入到队列中的最小时间间隔为指定间隔。而这将导致两个问题:

某些间隔被吞(如上面的定时器,当定时器加入队列到执行结束的时间大于1000ms时,下一个间隔就会被吞掉)

两个定时器执行的间隔小于规定的间隔(假设,某个定时器在950ms执行结束,而下一个定时器进来,事件队列刚好为空,主线程的同步任务又都执行结束,则下一个会立马执行,两个间隔只有50ms)

3.为了避免setIterval的问题,我们可以使用链式的setTimeout,或者递归setTimeout

setTimeout(function fn()
{ setTimeout(fn,interval); 
},interval);
function fn()
{
	// 定时器中要运行的代码
	setTimeout(function(){fn()},interval)
}

四,clearTimeoutclearInterval

1.我们可以使用clearTimeoutclearInterval来清除定时器,该函数的参数为定时器返回的编号。

let timer=setInterval(function(){console.log('1')},1000)
clearTimeout(timer)

五,注意事项

1.由于js的执行机制是事件循环机制,所以setTimeoutsetInterval实际延迟运行的时间会大于等于我们设置的时间。

六,防抖和节流

1.防抖和节流都是通过定时器完成的

(10) 防抖:将某个动作推迟执行,若在期间内在此触发动作,则清空计时器重新开始计时

var timer=null
function fd(){
	if(timer){
	clearTimeout(timer)}
	timer=setTimeout(function(){dosomething},500)}

(1)节流:某个动作在期间内只执行一次

var timer=null
function jl(){
	if(timer){
	return}
	timer=setTimeout(function(){
	dosomething;
	clearTimeout(timer)},500)
}

六,牛客网例题

1.实现一个打点计时器,要求
startend(包含 startend),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
返回的对象中需要包含一个 cancel 方法,用于停止定时操作
第一个数需要立即输出

当遇到这道题我一开始用了一个错误的方法:这种方法定时器在循环期间一口气创建,也就是每个定时器的开始计时的时间是几乎一样的,所以最后会一口气输出。

function count(start, end) {
    console.log(start)
    for(let i=1;i<=end-start;i++)
    {
        let count=setTimeout(()=>{
                   console.log(start+i)
                   },1000)
    }
    return {
        cancel(){
            clearTimeout(count)
        }
   }
}

若要用setTimeout方法,正确的是使用递归。

function count(start, end) {
	if(end>=start)
	{
	    console.log(start)
	    start++
	    var counttime = setTimeout(()=>
	    {	
	    	count(start,end)
	    },100)
    }
	else{
		clearTimeout(counttime)
	}
     return {
        cancel(){
            clearTimeout(counttime)
        }
        }
   }

正如上面所说我们是使用setTimeout递归来实现setInterval,因此我们当然还可以使用setInterval

function count(start, end) {
    console.log(start)
    let counttime = setInterval(
	()=>{
            console.log(start+1)
			start+=1
			if(start===end){
			    clearInterval(counttime )
			}
        },100)
    
    return {
        cancel(){
            clearInterval(counttime )
        }
   }
}
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值