setTimeout()基础/setInterval()基础
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列添加定时任务。初始接触它的人都觉得好简单,实际上真的如此么?这里记载下,一路对其使用姿势变迁的历程。
setTimeout()基础:
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
var timerId = setTimeout(func|code, delay)
上面代码中,setTimeout()
函数接受两个参数,第一个参数func|code
是将要推迟执行的函数名或者一段代码,第二个参数delay
是推迟执行的毫秒数。
console.log(1);
setTimeout('console.log(2)',1000);
console.log(3);
上面代码的输出结果就是1
,3
,2
,因为setTimeout()
指定第二行语句推迟1000
毫秒再执行(如果这在Sublime下运用插件以nodejs环境来执行,许解释器不同,会报错)。
需要注意的是,推迟执行的代码必须以字符串的形式,放入setTimeout()
,因为引擎内部使用eval()
函数,将字符串转为代码。如果推迟执行的是函数,则可以直接将函数名,放入setTimeout()
。一方面eval()
函数有安全顾虑,另一方面为了便于JavaScript引擎优化代码,setTimeout()
方法一般总是采用函数名的形式,就像下面这样。
function func(){
console.log(2);
} setTimeout(func,1000);
// 或者
setTimeout(function (){
console.log(2)
},1000);
==========================================================================
setInterval()基础
setInterval()
函数的用法与setTimeout()
完全一致,区别仅仅在于setInterval()
指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
<input type="button" onclick="clearInterval(timer)" value="stop">
<script>
var i = 1
var timer = setInterval(function() {
console.log(2);
}, 1000);
</script>
上面代码表示每隔1000
毫秒就输出一个2
,直到用户点击了停止按钮。
与setTimeout()
一样,除了前两个参数,setInterval()
方法还可以接受更多的参数,它们会传入回调函数,下面是一个例子。
function f(){
for (var i=0;i<arguments.length;i++){
console.log(arguments[i]);
}
}
setInterval(f, 1000, "Hello World");
// Hello World
// Hello World
// Hello World
// ...
如果网页不在浏览器的当前窗口(或tab),许多浏览器限制setInteral()
指定的反复运行的任务最多每秒执行一次。
setInterval()
指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的事件。因此实际上,两次执行之间的间隔会小于指定的时间。比如,setInterval()
指定每100ms
执行一次,每次执行需要5ms
,那么第一次执行结束后95
毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105
毫秒,那么它结束后,下一次执行就会立即开始。
var i = 1;
var timer = setInterval(function() {
alert(i++);
}, 2000);
上面代码每隔2000
毫秒,就跳出一个alert
对话框。如果用户一直不点击“确定”,整个浏览器就处于“堵塞”状态,后面的执行就一直无法触发,将会累积起来。举例来说,第一次跳出alert
对话框后,用户过了6000
毫秒才点击“确定”,那么第二次、第三次、第四次执行将累积起来,它们之间不会再有等待间隔。
为了确保两次执行之间有固定的间隔,可以不用setInterval()
,而是每次执行结束后,使用setTimeout()
指定下一次执行的具体时间。上面代码用setTimeout()
,可以改写如下。
var i = 1;
var timer = setTimeout(function() {
alert(i++);
timer = setTimeout(arguments.callee, 2000);
}, 2000);
上面代码可以确保两次执行的间隔是2000
毫秒。
根据这种思路,可以自己部署一个函数,实现间隔时间确定的setInterval()
的效果。
function interval(func, wait){
var interv = function(){
func.call(null);
setTimeout(interv, wait);
};
setTimeout(interv, wait);
}
interval(function(){
console.log(2);
},1000);
上面代码部署了一个interval()
函数,用循环调用setTimeout()
模拟了setInterval()
。
HTML 5标准规定,setInterval()
的最短间隔时间是10
毫秒,也就是说,小于10
毫秒的时间间隔会被调整到10
毫秒。
==============================
setInterval()运行机制
setInterval()
的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop
时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop
时重新判断。这意味着,setTimeout()
指定的代码,必须等到本次执行的所有代码都执行完,才会执行。
每一轮Event Loop
时,都会将“任务队列”中需要执行的任务,一次执行完。setTimeout()
和setInterval()
都是把任务添加到“任务队列”的尾部。因此,它们实际上要等到当前脚本的所有同步任务执行完,然后再等到本次Event Loop
的“任务队列”的所有任务执行完,才会开始执行。由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setTimeout()
和setInterval()
指定的任务,一定会按照预定时间执行。
这一点对于setInterval()
影响尤其大。
setInterval(function(){
console.log(2);
},1000);
(function (){
sleeping(3000);
})();
上面的第一行语句要求每隔1000
毫秒,就输出一个2
。但是,第二行语句需要3000
毫秒才能完成,请问会发生什么结果?
结果就是等到第二行语句运行完成以后,立刻连续输出三个2
,然后开始每隔1000
毫秒,输出一个2
。也就是说,setIntervel()
具有累积效应,如果某个操作特别耗时,超过了setInterval()
的时间间隔,排在后面的操作会被累积起来,然后在很短的时间内连续触发,这可能或造成性能问题(比如集中发出Ajax请求)。
上一示例,根据网友 @看吓不说话 指出,在Nodejs环境下测试,并不会连续输出三个2
;理由:setInterval()
在准备把回调函数加入到事件队列的时候,会判断队列中是否还有未执行的回调,如果有的话,它就不会再往队列中添加回调函数。
var count = 0;
var countId = setInterval(function() {
if(count >= 5){
clearInterval(countId)
}
count++;
console.log(2+ " time: " +Date.now());
}, 1000);
(function() {
var start = Date.now();
for(i=1; i<=200000000;i++){
if(i==200000000){
console.log(i);
}
}
console.log(Date.now() - start);
})();
打印测试结果,如下:
200000000
1771
2 time: 1457495719375
2 time: 1457495720378
2 time: 1457495721380
2 time: 1457495722383
2 time: 1457495723395
2 time: 1457495724397
[Finished in 8.5s]
为了进一步理解JavaScript的单线程模型,请看下面这段伪代码。
function init(){
{ 耗时5ms的某个操作 }
触发mouseClickEvent事件
{ 耗时5ms的某个操作 }
setInterval(timerTask,10);
{ 耗时5ms的某个操作 }
}
function handleMouseClick(){
耗时8ms的某个操作
}
function timerTask(){
耗时2ms的某个操作
}
init();
请问调用init
函数后,这段代码的运行顺序是怎样的?
0-15ms:运行init函数。
15-23ms:运行handleMouseClick函数。请注意,这个函数是在5ms时触发的,应该在那个时候就立即运行,但是由于单线程的关系,必须等到init函数完成之后再运行。
23-25ms:运行timerTask函数。这个函数是在10ms时触发的,规定每10ms运行一次,即在20ms、30ms、40ms等时候运行。由于20ms时,JavaScript线程还有任务在运行,因此必须延迟到前面任务完成时再运行。
30-32ms:运行timerTask函数。
40-42ms:运行timerTask函数。
对于setInterval()
得使用,个人建议是能不用尽量不用。涉及到必须要的定时器,前文已经叙述可以使用两个setTimeout()
嵌套组合来实现,并且还能规避掉一些问题得发生。涉及到要用它来制作动画( jQuery就使用setInterval()
来写动画,也是导致其慢原因之一),更建议使用requestAnimationFrame
(RAF),或者直接采用CSS来写(如果可以的话)。
requestAnimationFrame
比起setTimeout()
、setInterval()
的优势主要有两点:
requestAnimationFrame
会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60
帧。- 在隐藏或不可见的元素中,
requestAnimationFrame
将不会进行重绘或回流,这当然就意味着更少的的CPU,GPU和内存使用量。
======================================================================================
http://www.w3cplus.com/javascript/javaScript-setInterval.html
setTimeout()基础/setInterval()基础的更多相关文章
- setTimeout,setInterval原理
function a() { setTimeout(function(){alert(1)},0); alert(2); } a(); 和其他的编程语言一样,Javascript中的函数调用也是通过堆 ...
- JavaScript的setTimeout和setInterval的深入理解
发表过一片博客<跟着我用JavaScript写计时器>,比较基础.....有网友说应该写一下setTimeout的原理和机制,嗯,今天就来写一下吧: 直奔主题:setTimeout和set ...
- 【JavaScript】JavaScript中的Timer是怎么工作的( setTimeout,setInterval)
原文(http://www.yeeyan.org/articles/view/luosheng/24380) 作为入门者来说,了解JavaScript中timer的工作方式是很重要的.通常它们的表现行 ...
- setTimeout和setInterval区别
setTimeout和setInterval这两个函数, 大家肯定都不陌生, 但可能并不是每个用过这两个方法的同学, 都了解其内部的实质 甚至可能会错误的把两个实现定时调用的函数理解成了类似threa ...
- setTimeout,setInterval运行原理
function a() { setTimeout(function(){alert(1)},0); alert(2); } a(); 和其他的编程语言一样,Javascript中的函数调用也是通 ...
- js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)
javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...
- 聊聊setTimeout和setInterval线程
在聊setTimeout和setInterval这两个事件的前,先聊另外一个与之密切关联的知识点,那就是线程(thread).而线程有常常跟另外一个词语--“进程”一起出现.那么何为线程?何为线程呢? ...
- Javascript异步编程之setTimeout与setInterval详解分析(一)
Javascript异步编程之setTimeout与setInterval 在谈到异步编程时,本人最主要会从以下三个方面来总结异步编程(注意:特别解释:是总结,本人也是菜鸟,所以总结不好的,请各位大牛 ...
- 【转】Javascript异步编程之setTimeout与setInterval
Javascript异步编程之setTimeout与setInterval 转自:http://www.tuicool.com/articles/Ebueua 在谈到异步编程时,本人最主要会从以下三个 ...
随机推荐
- bzoj 4292: [PA2015]Równanie
Description 对于一个正整数n,定义f(n)为它十进制下每一位数字的平方的和.现在给定三个正整数k,a,b,请求出满足a<=n<=b且k*f(n)=n的n的个数. Input ...
- bzoj 4131: 并行博弈 (parallel)
bzoj 4131: 并行博弈 (parallel) Description lyp和ld在一个n*m的棋盘上玩翻转棋,游戏棋盘坐标假设为(x, y),1 ≤ x ≤ n,1 ≤ y ≤ m,这个游戏 ...
- hdu 1423 最长上升递增子序列
#include <iostream> #include <cstdio> #include <cstring> using namespace std; ; in ...
- Java数据结构-------Set
三种常用Set:HashSet.LinkedHashSet.TreeSet set类继承关系: 概述 Set是对对应Map的一种封装,Set中的元素不可以重复. HashSet对应 HashMap.L ...
- Codevs 4633 [Mz]树链剖分练习
4633 [Mz]树链剖分练习 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 大师 Master 题目描述 Description 给定一棵结点数为n的树,初始点权均为0,有依次q个 ...
- scrapy实战
采用scrapy实现对股票网站的爬取 功能描述: 技术路线:scrapy 目标:获取上交所和深交所所有股票名称和交易信息并存储 实例编写: 步骤1:建立工程和spider爬虫模板 步骤2:编写spid ...
- 理解printk函数【转】
转自:http://blog.csdn.net/Tommy_wxie/article/details/17026391 理解printk函数 Printk函数是在开发驱动过程中经常用到的一个函数,作用 ...
- 从零开始学习OpenCL开发(一)架构【转】
转自:http://blog.csdn.net/leonwei/article/details/8880012 多谢大家关注 转载本文请注明:http://blog.csdn.net/leonwei/ ...
- Alfred添加百度搜索
Alfred默认的搜索只有 google; amazon和wikipakia, 我想加个百度搜索,怎么添加呢? 1.首先添加百度搜索,添加http://www.baidu.com/s?wd={quer ...
- AC日记——[ZJOI2008]树的统计Count bzoj 1036
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 15007 Solved: 6092[Submit ...