定时和时间间隔异步
setTimeout( ) 在指定的时间后运行一段代码
setInterval( ) 以固定的时间间隔,重复运行一段代码
requestAnimationFrame( ) setInterval()的现代版本;在浏览器下一次重新绘制显示之前执行指定的代码块,从而允许动画在适当的帧率下运行,而不管它在什么环境中运行
这些函数设置的异步代码实际上在主线程上运行,只是在运行间隔间可以执行其他代码
这些函数不能保证在指定的确切时间后调用,但是保证至少延时这么多时间
- setTimeout()的参数&返回值
要运行的函数,或者函数引用
[时间(ms)]:指定时间后运行指定函数,缺省值为0
[更多的参数]:在指定函数运行时,希望传递给函数的值
返回值:一个表示当前延时任务标志符变量,可以用clearTimeout(该变量)
来取消这个任务
let greeting = setTimeout(function(){
alert("hello, Mr.Unknown");
},2000);
clearTimeout(greeting);
let hello = function(name){
alert("hello, Mr."+name);
};
setTimeout(hello, 0, "Well");
- setInterval()的参数&返回值
与setTimeout参数与返回值相同,只是执行多次,间隔不小于指定的时间
let clock = setInterval(function(){
let date = new Date();
let time = date.toLocaleTimeString();
document.getElementById('clock').textContent = time;
},1000);
clearInterval(clock, 3600);
Tips About setTimeout( ) & setInterval( )
setTimeout()的递归调用实现setInterval()的效果
- 递归的setTimeout()保证执行间隔延时相同,设置的延时参数不包括这段代码的执行时间,而setInterval()包括这段不确定的运行时间(因此延时任务本身耗时较长时不宜使用setInterval(),考虑使用递归setTimeout()替代)
- 递归的setTimeout()可以实现不同时间间隔的重复任务
立即执行的延时任务
这些延时任务实际上运行在主线程上,但是需要在主线程代码运行之后,才尽快调度执行延时回调
setTimeout(function() {
alert('World');
}, 0);
alert('Hello');
以上代码先 alert ‘Hello’,再 alert ‘World’
setTimeout(sth., 0)有着等主线程代码都运行完就立刻运行的特性
clearTimeout()和clearInterval()
实际上这两个函数实现是相同的,因此可以混用;但为了避免混淆以及代码规范,还是进行区分
requestAnimationFrame()
专门用于运行动画的setInterval(),在浏览器下一次重新绘制之前,运行指定的代码
常用的递归形式
function draw() {
--Drawing code goes here--
requestAnimationFrame(draw);
}
draw();
扩展:如果想执行一些简单的常数DOM动画,CSS动画可能更快,因为CSS动画是直接由浏览器内部代码而不是JavaScript计算的。但是,如果您正在做更复杂的事情,并且涉及DOM内不能直接访问的对象(例如二维画布API或WebGL对象)requestAnimationFrame()在大多数情况下是更好的选择
关于requestAnimationFrame()
- requestAnimationFrame()同样会返回一个标志符变量,可用**cancelAnimationFrame( )**取消
- 动画的流畅性直接取决于动画的帧速率,即每秒帧数(FPS)。这个数字越高,你的动画就越流畅
- 大多数屏幕的刷新率是60HZ,因此最理想的帧速率上限是每秒60帧
- requestAnimationFrame()总是尽可能地接近60FPS
- 然而当requestAnimationFrame()所刷新的东西在屏幕上不可见时,浏览器就不会浪费时间运行它了
- 加入时间戳
function getReqCallback() {
var count = 0;
var lastTimestamp = null;
return function req(timestamp) {
if (lastTimestamp === null ) {
lastTimestamp = timestamp;
}
count++;
console.log(timestamp - lastTimestamp + 'ms');
lastTimestamp = timestamp;
if (count < 100) {
requestAnimationFrame(req);
}
}
}
requestAnimationFrame(getReqCallback());
以上代码requestAnimationFrame()在调用req时会传参为当前时间
requestAnimationFrame()是比较新,性能好的API
2019/6/2