定时器

定时器基础

1
2
3
4
5
6
7
8
9
var timer1 = setTimeout(function(){

}, 1000);
console.log(timer1); //=> 1

var timer2 = setInterval(function(){

}, 1000);
console.log(timer2); //=> 2
  • 定时器的返回值: 当我们设置定时器(不管是setTimeout还是setInterval),都会有一个返回值,返回值是一个数字,代表当前实在浏览器中设置的第几个定时器(返回的是定时器序号)
  • setTimeout和setInterval虽然是处理不同需求的定时器,但是都是浏览器的定时器,所以设置的时候,返回的序号是依次排列的
  • setInterval设置完成定时器会有一个返回值,不管执行多少次,这个代表序号的返回值不变(设置定时器就有返回值,执行多少次是定时器的处理)

清除定时器

  • clearTimeout([定时器排队序号])
  • clearInterval([定时器排队序号])
  • 定时器需要手动清除
1
2
3
4
5
6
var t1 = setTimeout(function(){
//=> 当方法执行完成后,定时器没用了,我们清除定时器即可
//=> clearTimeout(t1);
clearInterval(t1); //=> 使用它也可以清除掉
t1 = null; //=> 我们手动把之前存储序号的变量赋值为null
}, 1000);

实现动画效果

1
2
3
4
5
6
7
8
9
10
11
12
function imgFade(curImg){
var n = 0;
var timer = setInterval(function(){
if(n > 1){
clearInterval(timer);
timer = null;
return;
}
n += 0.05;
utils.css(curImg, 'opacity', n);
}, 17); //=> 17ms是执行定时器动画相对比较理想的时间间隔
}

JS中的同步和异步编程

JS是单线程的(一次只能执行一个任务,当前任务没有完成,下面任务不进行处理)

同步编程(sync:synchronize):任务是按照顺序一件件的完成的,当前任务没有完成,下面的任务部进行处理

异步编程(async)当前任务再等待执行的时候,我们不去执行,继续完成下面的任务,当下面的任务完成后,而是也到达等待的时间了,采取完成当前的任务

定时器都是异步编程的

所有的时间绑定都是异步编程的

AJAX中有异步编程

有些人把回调函数当作异步编程(牵强)

1
2
3
4
5
6
7
8
9
//=> 同步编程以及如何验证当前任务小号的时间或者性能
var startTime = new Date();
for(var i = 0; i < 1000000; i += 1){
if(i === 999999){
console.log('no');
}
}
console.log(new Data() - startTime);
console.log('ok');
1
2
3
//=> 项目中要避免死循环,因为循环是同步编程,当前循环无法结束,后续的任务操作都执行不了
while(1===1){}
console.log(1);
1
2
3
4
5
6
var n = 0;
setTimeout(function(){
n++;
console.log(n);
}, 1000);
console.log(n);

同步异步编程的核心原理

  • JS中有两个任务队列(存放任务列表的空间就是任务队列)
  • 1、主任务队列:同步执行任务(从上到下一次执行)
    2、等待任务队列:异步执行任务(主任务队列中的任务全部完成,把等待任务队列中的任务拿到主任务队列中执行(哪一个先到,先找哪一个,同时到,按照创建顺序来),当前这个任务完成后,再到等待中去找其他任务)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
setTimeout(function(){
console.log(1);
}, 50);

setTimeout(function(){
console.log(2);
}, 10);

setTimeout(function(){
console.log(3);
}, 30);

for(var i = 0; i < 100000000; i += 1){
if(i === 99999999){
console.log(4);
}
};
console.log(5);

JS中固定步长和固定时间的匀速运动动画

1、步长固定(每走一步多少固定),但是多长时间运动完成不固定

1
2
3
4
5
6
7
8
9
10
11
12
13
var oBox = document.getElementById('box'),
target = document.documentElement.clientWidth - oBox.offsetWidth;
//=> 动画:每隔一段时间都在自己原有的left基础上累加步长10排序,一直到达目标值结束
var timer = setInterval(function(){
var curL = oBox.offsetLeft;
curL += 10;
oBox.style.left = curL + 'px';
if(curL >= target){
oBox.style.left = target + 'px';
clearInterval(timer);
timer = null;
}
}, 17);

2、固定时间的匀速动画

  • target: 目标值
  • start: 起始值
  • change:总距离 target-start
  • duration: 总时间
  • time:已经运动的时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function linear(time, begin, change, duration){
return time/duration*change + begin
}
var oBox = document.getElementById('box'),
time = 0,
duration = 1000,
begin = parseInt(getComputedStyle(oBox).left),
target = document.documentElement.clientWidth - oBox.offsetWidth,
change = target - begin;

var timer = setInterval(function(){
time += 17;
var curL = linear(time, begin, change, duration);
if(time >= duration){
clearInterval(timer);
timer = null;
curL = target;
}
oBox.style.left = curL + 'px';
}, 17);

多方向固定时间匀速运动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}

html, body {
width: 100%;
height: 100%;
}

.box {
width: 100px;
height: 100px;
position: absolute;
left: 0;
top: 0;
background: #ff6700;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.getElementsByClassName('box')[0];
var time = 0,
duration = 1000;
var begin = {
left: box.offsetLeft,
top: box.offsetTop,
opacity: 1
};
var target = {
left: document.body.clientWidth - box.offsetWidth,
top: document.body.clientHeight - box.offsetHeight,
opacity: 0.2
};
var change = {};
for(var key in target){
if(target.hasOwnProperty(key)){
change[key] = target[key] - begin[key];
}
}

function linear(t, b, c, d){
return t / d * c + b;
}

box.timer = setInterval(function(){
if(time >= duration-17){
box.style.left = target.left + 'px';
box.style.top = target.top + 'px';
clearInterval(box.timer);
return;
}
time += 17;
var curPos = {};
for(var key in change){
curPos[key] = linear(time, begin[key], change[key], duration);
}

for(var key in curPos){
if(key !== 'opacity'){
box.style[key] = curPos[key] + 'px';
}else{
box.style[key] = curPos[key];
}

}
}, 17)
</script>
</body>
</html>