进一步理解setTimeout与setInterval

进一步理解setTimeout与setInterval

有一段时间没有写博客了,因为之前一段时间都在实习,接触了PHP和MySQL的使用,学习了ThinkPHP5的基本用法,然后就没再去总结心得(正确来说是平时实习没接触到JS的难点)。但是最近,因为一个需求,再次让我觉得我JS学得还真的不够多,还是很浅的知识。


  在实习的时候,遇到这么一个需求:在一个竞猜页面中,有5个定时器,分别对应每个进行倒计时,每个setInterval的操作都是进行Ajax请求,去后台获取倒计时时间,显示到页面上。

  首先每当用户进入主页面时,会先触发一个每30秒进行一次Ajax请求的定时器。当点击进入竞猜页面的按钮时,会触发另外五个定时器(页面并没有跳转,URL没改变)所以一个页面上会有一个30秒的定时器,然后至少五个1秒的定时器,每个定时器都是进行Ajax请求。
  首先先从2个计时器分析一下各自的类型(只是方便理解的说法):

  1. setTimeout():当特定的时间过去之后,将执行代码插入到队列
  2. setInterval():每隔一段设置的时间之后,就运行一次执行代码

  然后在面对这个需求的时候,我很理所当然地认为,需求是应该这么实现的:

  1. 首先在window.onload的时候就触发设置一个30秒的定时器,并且进行Ajax请求
  2. 然后给按钮添加一个点击时间,点击的时候切换第二视图,并且激活五个1秒的定时器
  3. 竞猜页面的退出按钮也添加一个点击时间,主要用作清除那5个定时器
  4. 当然,退出页面也需要一个window.unonload来清楚那个30秒的定时器

以上步骤无非就是简单的不断setInterval,当我敲完代码的时候,我就想到了一个问题:

  这样频繁的进行AJAX请求会不会卡掉页面。而且,好像时间上有冲突了。
  然后,自制了6个同样情况的定时器,然后进行记录,观看耗时

5个定时器的Waterfall
某一个请求的Timing

  这次模拟并没有出现当时在公司时出现的情况(或许是我测试的请求的PHP文件执行时间太短):当时间出现重叠时,页面会卡住,并且查看chrome的NetWork,发现请求卡住了,然后过一两秒后,才再次出现请求。然后每次的请求都没有指定的间隔时间

  我猜想的原因是:由于JavaScript的单线程机制,浏览器无论什么时候都是只有一个JS线程在执行JS程序,这或能就能解释出现的上图情况。
而在《JavaScript高级程序设计》中提到setInterval()的问题有两个:

1、某些间隔会被跳过;
2、多个定时器的代码执行之间的间隔可能会比预期的小

  就是说定时器会出现一种情况:
如果函数执行的时间太长,例如如下图的func中的代码func1执行了400ms,这个时候JavaScript的引擎会原本根据时间而定的在300ms和400ms的函数全部跳过,然后等func1执行完成后,立即执行下一个定时器函数。也就是说,只要处理完func1,立即进入下一次定时器代码,并且中途没有任何的停顿。
定时器队列

那我们又要如何去解决这个问题呢?就是保持每次执行之后的时间间隔?
就是使用setTimeout链式调用,

    setTimeout(function(){
          // 其他代码
          setTimeout(arguments.callee, interval);
     }, interval);

这种写法的好处就是每次代码执行完之前,不会在队列中加入任何定时器代码,所以这样就能确保下次代码执行之前,有一个指定的时间间隔,再去执行下一个执行代码。

这样我们就弄懂了问题出现的大概原因
1、会出现卡住的情况:因为单线程的机制,不能同时进行2个请求所以会卡住
2、卡住之后出现了没有时间间隔的请求:因为如果函数1的操作时间过长,那么,中间的时间间隔就会被忽略,然后立即执行下一个函数。

后面,我会再出一篇文章,如何顺利地解决这个问题,大概的意思就是建立一个时间管理中心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值