js中setTimeout的妙用--防止循環(huán)超時(shí)
上個(gè)周日,介紹了如何使用setTimeout代替setInterval進(jìn)行間歇調(diào)用,這個(gè)周日,繼續(xù)來講《JavaScript高級程序設(shè)計(jì)》這本書里面,對于setTimeout的另一種妙用——防止循環(huán)超時(shí)
【這是鋪墊,為故事的高潮埋下伏筆】
JS是單線程的,一個(gè)代碼塊里面的代碼,只能按順序從上到下執(zhí)行,所以如果中間有一塊代碼,執(zhí)行起來非常耗時(shí),就會導(dǎo)致下面的代碼無法執(zhí)行,出現(xiàn)瀏覽器假死的狀態(tài)。
JS的耗時(shí)操作,常見的有兩種 1.向服務(wù)器發(fā)起請求 2.對數(shù)組的循環(huán)操作 (當(dāng)然,還有一種,就是把1和2合在一起,叫做 在循環(huán)操作里面向服務(wù)器發(fā)出請求,哈哈哈,實(shí)際項(xiàng)目里面經(jīng)常有人這么干)
解決這兩種耗時(shí)操作的思路都是一樣的——異步編程。JS的異步編程,并不是多線程,因?yàn)檎缟厦嫠f的,JS是單線程的。JS的異步,直觀上的理解,就是延時(shí)和回調(diào)。
對于第一種耗時(shí)情況,我們采用的是ajax異步請求,待耗時(shí)的請求返回結(jié)果時(shí),進(jìn)行回調(diào)操作。
對于第二種耗時(shí)情況,則可以使用本文即將介紹的方法,setTimeout延時(shí)調(diào)用,進(jìn)行數(shù)組分塊處理。
【這才是高潮】
假設(shè)我們要處理一個(gè)大小為100的數(shù)組,對于數(shù)組中每個(gè)元素,都需要執(zhí)行大量的處理,每個(gè)元素大約需要1s的處理時(shí)間;
并且我們認(rèn)為,程序后面的代碼,不會依賴于我們對這個(gè)數(shù)組的處理結(jié)果。
于是就有了下面這段代碼,以兩種方式來處理這個(gè)數(shù)組,一種是常規(guī)方式,一種是setTImeout的數(shù)組分塊處理
var processTime = 0; //常規(guī)操作 tcCircle(); //注釋上面的代碼 放開下面注釋 以執(zhí)行setTimeout數(shù)組分塊操作 //tcCircleUseSetTimeout(); //time consuming circle function tcCircle(){ var arr = new Array(100); for(var i=0;i<arr.length;i++){ process(arr[i]); } //頁面標(biāo)題欄一直轉(zhuǎn)圈 且下面的語句遲遲無法執(zhí)行 console.log("important process"); console.log("finish!"); } function tcCircleUseSetTimeout(){ var arr = new Array(100); setTimeout(function(){ var ele = arr.shift(); process(ele); if(arr.length>0){ setTimeout(arguments.callee,100); } },100); console.log("important process"); console.log("finish!"); } function process(ele){ console.log("process"+(++processTime)); //模擬長時(shí)間的處理過程 sleep(1000); } function sleep(sleepTime){ var start=new Date().getTime(); while(true){ if(new Date().getTime()-start>sleepTime){ break; } } }
首先我們執(zhí)行常規(guī)的操作,由于是單線程,可想而知,執(zhí)行完這段程序,至少要 1*100 = 100s,并且瀏覽器會出現(xiàn)假死
然后我們執(zhí)行setTimeout方式的方法,setTImeout的方式,我們每次只操作數(shù)組里面的一個(gè)對象,并且在每次操作之間,設(shè)置了100ms的延時(shí),供js引擎執(zhí)行主干的代碼,因此,很明顯,執(zhí)行的效果非常棒!
我們看到,不僅瀏覽器的標(biāo)題欄不會轉(zhuǎn)菊花了,控制臺也很快就打印出 我們在代碼最后面打印的語句,說明主干程序已經(jīng)走完,數(shù)組的處理則定時(shí)執(zhí)行著。
通過這樣的優(yōu)化,我們的程序給用戶的體驗(yàn)提示了許多,當(dāng)然,這里只是書中介紹的一種方法,我相信還有很多其他實(shí)現(xiàn)方式,比如我現(xiàn)在可以想到的就有promise,有機(jī)會我會補(bǔ)充一下,大家也可以暢所欲言,看看有什么其他更好的方法來對付這種循環(huán)耗時(shí)操作!
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
JavaScript模仿Pinterest實(shí)現(xiàn)圖片預(yù)加載功能
圖片預(yù)加載是web開發(fā)中一種應(yīng)用相當(dāng)廣泛的技術(shù),比如我們在做圖片翻轉(zhuǎn)顯示等特效的時(shí)候,為了讓圖片在轉(zhuǎn)換的時(shí)候不出現(xiàn)等待,我們最好是先讓圖片下載到本地,然后在繼續(xù)執(zhí)行后續(xù)的操作。今天本文主要介紹的是利用JS模仿Pinterest圖片社交網(wǎng)站的圖片預(yù)加載功能。2016-10-10BootStrap實(shí)現(xiàn)郵件列表的分頁和模態(tài)框添加郵件的功能
這篇文章主要介紹了bootstrap分頁,模態(tài)框,實(shí)現(xiàn)郵件列表的分頁,和模態(tài)框添加郵件的功能的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Openlayers實(shí)現(xiàn)根據(jù)半徑繪制圓形
這篇文章主要介紹了利用Openlayers實(shí)現(xiàn)繪制三個(gè)圓形,繪制完成之后,三個(gè)圓心連接起來,然后標(biāo)記出每兩個(gè)圓心之間的距離,感興趣的可以了解一下2022-08-08js版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性
ES全稱ECMAScript,ECMAScript是ECMA制定的標(biāo)準(zhǔn)化腳本語言,本文講述Javascript[ECMAScript]版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]的新特性,幫助朋友們更好的熟悉和使用Javascript2024-11-11前端實(shí)現(xiàn)圖片或視頻預(yù)覽的三種方法總結(jié)
在JavaScript中實(shí)現(xiàn)前端圖片上傳即時(shí)預(yù)覽功能是一項(xiàng)常見的需求,特別是在網(wǎng)頁交互設(shè)計(jì)中,這篇文章主要給大家介紹了關(guān)于前端實(shí)現(xiàn)圖片或視頻預(yù)覽的三種方法,需要的朋友可以參考下2024-06-06JavaScript開發(fā)網(wǎng)頁中不常用但很重要的特性用法
JavaScript中的Proxy、WeakMap、WeakSet、Generator函數(shù)、Symbol、CustomEvent、事件委托和Intl對象等特性提供了強(qiáng)大的功能,這些特性在復(fù)雜項(xiàng)目中發(fā)揮著重要作用,本文就給大家介紹了這些特性的用法,需要的朋友可以參考下2024-12-12網(wǎng)頁前端登錄js按Enter回車鍵實(shí)現(xiàn)登陸的兩種方法
下面小編就為大家?guī)硪黄W(wǎng)頁前端登錄js按Enter回車鍵實(shí)現(xiàn)登陸的兩種方法。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考2016-05-05