setTimeout函數(shù)的神奇使用
【寫在前面的胡言亂語(yǔ)】
自從大三開(kāi)始實(shí)習(xí)之后,就沒(méi)有寫博客了,雖然學(xué)了很多東西,但是如果沒(méi)有進(jìn)行總結(jié)和分享,學(xué)的東西就很容易忘記,而且不進(jìn)行分享,就不會(huì)手動(dòng)去敲代碼,這樣對(duì)知識(shí)的理解就不夠透徹。
現(xiàn)在畢業(yè)半年多了,最近學(xué)習(xí)了《JavaScript高級(jí)程序設(shè)計(jì)》這本書(shū),受益匪淺,看了才知道雖然自己寫了那么多JS,但是對(duì)JS的理解最多就只是中下水平。
現(xiàn)在看第二遍,邊看邊敲代碼,邊分享,希望看到這篇文章的你,能有所收獲。
【這是正文】
《JavaScript高級(jí)程序設(shè)計(jì)》這本書(shū)里面,介紹了很多關(guān)于setTimeout函數(shù)的神奇使用,今天來(lái)介紹下第一個(gè)——使用setTimeout代替setInterval進(jìn)行間歇調(diào)用。
書(shū)中是這么說(shuō)的
“在開(kāi)發(fā)環(huán)境下,很少使用間歇調(diào)用(setInterval),原因是后一個(gè)間歇調(diào)用很可能在前一個(gè)間歇調(diào)用結(jié)束前啟動(dòng)”。
這話怎么理解呢?
首先我們來(lái)看一下一般情況下的setInterval函數(shù)的使用,以及如何使用setTimeout代替setInterval
var executeTimes = 0;
var intervalTime = 500;
var intervalId = null;
// 放開(kāi)下面的注釋運(yùn)行setInterval的Demo
intervalId = setInterval(intervalFun,intervalTime);
// 放開(kāi)下面的注釋運(yùn)行setTimeout的Demo
// setTimeout(timeOutFun,intervalTime);
function intervalFun(){
executeTimes++;
console.log("doIntervalFun——"+executeTimes);
if(executeTimes==5){
clearInterval(intervalId);
}
}
function timeOutFun(){
executeTimes++;
console.log("doTimeOutFun——"+executeTimes);
if(executeTimes<5){
setTimeout(arguments.callee,intervalTime);
}
}
代碼比較簡(jiǎn)單,我們只是在setTimeout的方法里面又調(diào)用了一次setTimeout,就可以達(dá)到間歇調(diào)用的目的。
重點(diǎn)來(lái)了,為什么作者建議我們使用setTimeout代替setInterval呢?setTimeout式的間歇調(diào)用和傳統(tǒng)的setInterval間歇調(diào)用有什么區(qū)別呢?
區(qū)別在于,setInterval間歇調(diào)用,是在前一個(gè)方法執(zhí)行前,就開(kāi)始計(jì)時(shí),比如間歇時(shí)間是500ms,那么不管那時(shí)候前一個(gè)方法是否已經(jīng)執(zhí)行完畢,都會(huì)把后一個(gè)方法放入執(zhí)行的序列中。這時(shí)候就會(huì)發(fā)生一個(gè)問(wèn)題,假如前一個(gè)方法的執(zhí)行時(shí)間超過(guò)500ms,加入是1000ms,那么就意味著,前一個(gè)方法執(zhí)行結(jié)束后,后一個(gè)方法馬上就會(huì)執(zhí)行,因?yàn)榇藭r(shí)間歇時(shí)間已經(jīng)超過(guò)500ms了。
書(shū)中沒(méi)有給出代碼證明這個(gè)結(jié)論,于是自己寫了一段代碼來(lái)驗(yàn)證。
var executeTimes = 0;
var intervalTime = 500;
var intervalId = null;
var oriTime = new Date().getTime();
// 放開(kāi)下面的注釋運(yùn)行setInterval的Demo
intervalId = setInterval(intervalFun,intervalTime);
// 放開(kāi)下面的注釋運(yùn)行setTimeout的Demo
// setTimeout(timeOutFun,intervalTime);
function intervalFun(){
executeTimes++;
var nowExecuteTimes = executeTimes;
var timeDiff = new Date().getTime() - oriTime;
console.log("doIntervalFun——"+nowExecuteTimes+", after " + timeDiff + "ms");
var delayParam = 0;
sleep(1000);
console.log("doIntervalFun——"+nowExecuteTimes+" finish !");
if(executeTimes==5){
clearInterval(intervalId);
}
}
function timeOutFun(){
executeTimes++;
var nowExecuteTimes = executeTimes;
var timeDiff = new Date().getTime() - oriTime;
console.log("doTimeOutFun——"+nowExecuteTimes+", after " + timeDiff + "ms");
var delayParam = 0;
sleep(1000);
console.log("doTimeOutFun——"+nowExecuteTimes+" finish !");
if(executeTimes<5){
setTimeout(arguments.callee,intervalTime);
}
}
function sleep(sleepTime){
var start=new Date().getTime();
while(true){
if(new Date().getTime()-start>sleepTime){
break;
}
}
}
(這里使用大牛提供的sleep函數(shù)來(lái)模擬函數(shù)運(yùn)行的時(shí)間)
執(zhí)行setInterval的Demo方法,看控制臺(tái)

可以發(fā)現(xiàn),fun2和fun1開(kāi)始的間歇接近1000ms,剛好就是fun1的執(zhí)行時(shí)間,也就意味著fun1執(zhí)行完后fun2馬上就執(zhí)行了,和我們間歇調(diào)用的初衷背道而馳。
我們注釋掉setInterval的Demo方法,放開(kāi)setTimeout的Demo方法,運(yùn)行,查看控制臺(tái)

這下終于正常了,fun1和fun2相差了1500ms = 1000 + 500,fun2在fun1執(zhí)行完的500ms后執(zhí)行。
不知道你有沒(méi)有和我一樣腦洞大開(kāi),反正我是感覺(jué)視野又開(kāi)闊了一點(diǎn),setTimeout的妙用還有很多,下次接著聊!
- 深入理解setTimeout函數(shù)和setInterval函數(shù)
- setTimeout函數(shù)兼容各主流瀏覽器運(yùn)行執(zhí)行效果實(shí)例
- 解決火狐瀏覽器下JS setTimeout函數(shù)不兼容失效不執(zhí)行的方法
- jQuery setTimeout()函數(shù)使用方法
- js函數(shù)setTimeout延遲執(zhí)行的簡(jiǎn)單介紹
- JS中setInterval、setTimeout不能傳遞帶參數(shù)的函數(shù)的解決方案
- js函數(shù)使用技巧之 setTimeout(function(){},0)
- javascript setTimeout()傳遞函數(shù)參數(shù)(包括傳遞對(duì)象參數(shù))
- 定時(shí)器(setTimeout/setInterval)調(diào)用帶參函數(shù)失效解決方法
- 給c#添加SetTimeout和SetInterval函數(shù)
相關(guān)文章
Underscore.js 的模板功能介紹與應(yīng)用
Underscore是一個(gè)非常實(shí)用的JavaScript庫(kù),提供許多編程時(shí)需要的功能的支持,他在不擴(kuò)展任何JavaScript的原生對(duì)象的情況下提供很多實(shí)用的功能,需要了解的朋友可以詳細(xì)參考下2012-12-12
JavaScript+html5 canvas實(shí)現(xiàn)圖片破碎重組動(dòng)畫特效
這篇文章主要介紹了JavaScript+html5 canvas實(shí)現(xiàn)破碎重組的視頻特效,感興趣的小伙伴們可以參考一下2016-02-02
使用auto.js實(shí)現(xiàn)自動(dòng)化每日打卡功能
這篇文章主要介紹了使用auto.js實(shí)現(xiàn)自動(dòng)化每日打卡,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08
JavaScript惰性求值的一種實(shí)現(xiàn)方法示例
這篇文章主要給大家介紹了關(guān)于JavaScript惰性求值的一種實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01
關(guān)于同時(shí)使用swiper和echarts遇到的問(wèn)題及解決方法
這篇文章主要介紹了關(guān)于同時(shí)使用swiper和echarts遇到的問(wèn)題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
Javascript獲取與設(shè)置ckeditor數(shù)據(jù)的實(shí)現(xiàn)方法
最近編輯器后臺(tái)升級(jí)成了ckeditor,但原來(lái)后臺(tái)有很多對(duì)應(yīng)編輯器內(nèi)容的替換功能,那么就需要用js獲取ckeditor編輯器里面的內(nèi)容,這里就為大家介紹一下具體的實(shí)現(xiàn)方法2023-08-08

