js定时器,你所要了解的那点事

背景:
1.数据展示页加一个自动刷新功能,让用户看到最新数据。 
2.加个定时,过*(时间段)后执行,实现xx效果。
3.调整一下这几个事件响应的执行顺序等等。。。
复制代码

开发过程中我们常常要用到定时器去完成某些需求。js为我们准备了两个函数:setTimeout和setInterval,我们在进入主题之前,先简单介绍一下它们

1.setTimeout:
var timerId =setTimeout(function(){
    //do    
},delay)

2.setInterval
var timerId2 = setInterval(function() {
    //do
}, delay)
//delay 时间周期
复制代码

首先,它们都会返回一个整数编号用来表示定时器。将这个值传给各自的clear方法可以取消定时。

其次,setTimeout是期望推迟(delay)ms后执行函数, setInterval则是期望间隔(delay)ms就执行一次函数。

为什么只是说期望那?上一个?瞧瞧

var start_date = 0;
setTimeout(function(){
	var end_date = new Date().getTime()/1000
	console.log('enter setTimeout date : ' +  end_date)
	console.log('time interval : '  + (end_date - start_date) + '秒')
},1000)
function bulky(){
	start_date = new Date().getTime()/1000;
	console.log("bulky start date : " + start_date)
	for(var i=0;i<100000;i++){
		for(var j=0;j<100000;j++){
			var k = 0;
			k = k*k;
		}
	}
}
bulky()
复制代码

先预测一下结果再运行代码,结果如下:

跟你想象中的结果一样吗?你会发现setTimeout并不是像它期望的那样----延迟1s就执行,而是要等待bulky()执行结束后才执行,这就是定时器不定时的情形。

定时器是怎么实现定时的?为什么会出现不定时的情况?

首先,要明确的一点:javascript是以单线程的方式运行的。JavaScript的主要用途是与用户互动,以及操作DOM。若以多线程的方式,则可能出现冲突。假设有两个线程同时操作一个DOM元素,线程1要求浏览器删除DOM,而线程2却要求修改DOM样式,这时浏览器就无法决定采用哪个线程的操作。当然,我们可以为浏览器引入“锁”的机制来解决这些冲突,但大大提高复杂性,所以 JavaScript从诞生开始就选择了单线程执行。在某一时刻内只能执行特定的一个任务,并且会阻塞其它任务执行。

但是JavaScript 有个基于“Event Loop”并发的模型(不是并行)。前者是逻辑上的同时发生,而后者是物理上的同时发生。所以,单核处理器也能实现并发。

上图说明一下并发和并行:

再上图说明一下Event Loop

js既然是单线程的,也就意味着所有任务需要排队。所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,形成了一个执行栈(execution context stack)

  • 异步任务指的是,不进入主线程,而进入"任务队列"(task queue)的任务。"任务队列"是一个事件的队列(可以当作消息的队列来理解)。IO设备完成一项任务or异步任务有了运行结果,就在"任务队列"中添加一个事件,表示相关的操作可以进入"执行栈",就等着执行栈调用了。

参照Event Loop的图,说一下大致的流程----> 执行栈中流式执行函数(同步任务),可能会调用API在任务队列中加入事件(onlick,onload等等)但并不执行。只有当前执行栈没有其他操作时,任务队列才会入执行栈中,执行

原理讲完了,回到正题。因为setTimeout, setInterval是异步任务,调用之后不会直接进入执行栈,而是进入任务队列,所以只有等到当前执行栈没有其他操作,它们才会进入执行栈中执行, 以上就是为什么定时器不总是定时的原因了。

哦,对了如果delay时间周期设为0,相当于一个插队操作

举例

?献上:

function f1(){
	console.log('f1')
}
function f2(){
	console.log('f2')
}
function f3(){
	console.log('f3')
	setTimeout(function(){
		console.log('setTimeout1')
	},2000)
}
setTimeout(function(){
	console.log('setTimeout2')
},3000)
setTimeout(function(){
	console.log('setTimeout3')
},1000)
setTimeout(function(){
	console.log('setTimeout4')
},0)

f1()
f2()
f3()
复制代码

运行结果

好了,以上内容就是我对js定时器的认识,希望可以帮助到你

未经本人允许,不得转载。文章有疏漏浅薄之处,请各位大神斧正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值