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