JavaScript:异步 setTimeout

setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。

function showDate(){
var date=new Date();
console.log(date);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){showDate();},10000);
console.log("cc");
showDate();

可以发现setTimeout内部的function是等待10s以后再执行的。

把时间改为0

 发现它还是最后执行的

类似异步

更具体的,更详细的

Date.prototype.format = function(formatStr) 
{   
    var str = formatStr;   
    var Week = ['','','','','','',''];  
  
    str=str.replace(/yyyy|YYYY/,this.getFullYear());   
    str=str.replace(/yy|YY/,(this.getYear() % 100)>9?(this.getYear() % 100).toString():'0' + (this.getYear() % 100));   
    //
    this.setMonth(this.getMonth()+1);
    str=str.replace(/MM/,this.getMonth()>9?this.getMonth().toString():'0' + this.getMonth());   
    str=str.replace(/M/g,this.getMonth());   
  
    str=str.replace(/w|W/g,Week[this.getDay()]);   
  
    str=str.replace(/dd|DD/,this.getDate()>9?this.getDate().toString():'0' + this.getDate());   
    str=str.replace(/d|D/g,this.getDate());   
  
    str=str.replace(/hh|HH/,this.getHours()>9?this.getHours().toString():'0' + this.getHours());   
    str=str.replace(/h|H/g,this.getHours());   
    str=str.replace(/mm/,this.getMinutes()>9?this.getMinutes().toString():'0' + this.getMinutes());   
    str=str.replace(/m/g,this.getMinutes());   
  
    str=str.replace(/ss|SS/,this.getSeconds()>9?this.getSeconds().toString():'0' + this.getSeconds());   
    str=str.replace(/s|S/g,this.getSeconds()); 
    
    str=str.replace(/ffff/,this.getMilliseconds());
  
    return str;   
}   

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:ffff");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){showDate();},1000);
console.log("cc");
showDate();

时间为100微秒

差距都差不多,更setTimeout间隔时间无关.

那么setTimeout是不是就是运行到setTimeout时就在任务队列中添加一个方法,setTimeout时间到了就运行该方法?

其实发现不是

有特殊情况:

假如setTimeout的间隔时间小于任务队列后面运行的时间:

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:ffff");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){console.log("bbb");showDate();},3000);
console.log("cc");
showDate();
console.log("begin");
for(var i=0;i<10000000;i++){
}
console.log("end");
showDate();

 发现:setTimeout的间隔时间是近5.5s,for循环花费的时间也大概是5.5s

说明:在这种setTimeout间隔时间小于任务队列运行时间的情况下,setTimeout中的方法一直到队列任务全部完成以后才执行,间隔时间有任务队列花费时间决定。

setTimeout间隔时间大于队列任务运行时间,实际任务中大部分是这种情况

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:ffff");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){console.log("bbb");showDate();},30000);
console.log("cc");
showDate();
console.log("begin");
for(var i=0;i<10000000;i++){
}
console.log("end");
showDate();

发现尽管for循环中花费了5.5s,但是setTimeout的间隔时间依然是30s.

这时再回头看看那个setTimeout(function(){},0),间隔时间是0的情况

发现setTimeout中的方法就应该在任务队列的最后运行。

证明:js引擎按照预编译的顺序运行队列任务,这时setTimeout中的方法没有在队列中,间隔时间到了以后将setTimeout中的方法添加到任务队列中

所以,setTimeout中的方法都是在预编译中的方法后运行的

多个setTimeout中的方法运行顺序是由它们加入队列的顺序决定的。

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:f");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){console.log("bbb");showDate();},3000);
console.log("cc");
showDate();
console.log("begin");
for(var i=0;i<10000000;i++){
}
console.log("end");
showDate();
console.log("begin2");
for(var i=0;i<10000000;i++){
}
console.log("end2");
showDate();

继续分析:

1.两个setTimeout

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:ffff");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){console.log("bbb");showDate();},3000);
console.log("cc");
setTimeout(function(){console.log("ccc");showDate();},1000);
showDate();

2.第一个setTimeout的方法花费时间大于第二个setTimeout的间隔时间:

function showDate(){
var date=new Date();
var str=date.format("yyyy-MM-dd HH:mm:ss:ffff");
console.log(str);
}
console.log("aa");
showDate();
console.log("bb");
setTimeout(function(){console.log("bbb");showDate();},3000);
console.log("cc");
setTimeout(function(){
console.log("ccc");
showDate();
console.log("begin");
for(var i=0;i<300000000;i++){
}
console.log("end");
showDate();
},1000);
showDate();

发现:for循环花费了6s多,bbb是紧接着前一个setTimeout方法的,

http://www.cnblogs.com/littledu/articles/2607211.html

http://www.laruence.com/2009/09/23/1089.html

http://www.cnblogs.com/rubylouvre/archive/2009/08/20/1550264.html

http://www.cnblogs.com/rubylouvre/archive/2011/03/14/1982699.html

原文地址:https://www.cnblogs.com/hongdada/p/3359668.html