上個周日,介紹了如何使用setTimeout代替setInterval進行間歇調用,這個周日,繼續來講《JavaScript高級程序設計》這本書里面,對于setTimeout的另一種妙用――防止循環超時
【這是鋪墊,為故事的高潮埋下伏筆】
JS是單線程的,一個代碼塊里面的代碼,只能按順序從上到下執行,所以如果中間有一塊代碼,執行起來非常耗時,就會導致下面的代碼無法執行,出現瀏覽器假死的狀態。
JS的耗時操作,常見的有兩種 1.向服務器發起請求 2.對數組的循環操作 (當然,還有一種,就是把1和2合在一起,叫做 在循環操作里面向服務器發出請求,哈哈哈,實際項目里面經常有人這么干)
解決這兩種耗時操作的思路都是一樣的――異步編程。JS的異步編程,并不是多線程,因為正如上面所說的,JS是單線程的。JS的異步,直觀上的理解,就是延時和回調。
對于第一種耗時情況,我們采用的是ajax異步請求,待耗時的請求返回結果時,進行回調操作。
對于第二種耗時情況,則可以使用本文即將介紹的方法,setTimeout延時調用,進行數組分塊處理。
【這才是高潮】
假設我們要處理一個大小為100的數組,對于數組中每個元素,都需要執行大量的處理,每個元素大約需要1s的處理時間;
并且我們認為,程序后面的代碼,不會依賴于我們對這個數組的處理結果。
于是就有了下面這段代碼,以兩種方式來處理這個數組,一種是常規方式,一種是setTImeout的數組分塊處理
var processTime = 0;//常規操作tcCircle();//注釋上面的代碼 放開下面注釋 以執行setTimeout數組分塊操作//tcCircleUseSetTimeout();//time consuming circlefunction tcCircle(){ var arr = new Array(100); for(var i=0;i<arr.length;i++){ process(arr[i]); } //頁面標題欄一直轉圈 且下面的語句遲遲無法執行 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)); //模擬長時間的處理過程 sleep(1000);}function sleep(sleepTime){ var start=new Date().getTime(); while(true){ if(new Date().getTime()-start>sleepTime){ break; } }}首先我們執行常規的操作,由于是單線程,可想而知,執行完這段程序,至少要 1*100 = 100s,并且瀏覽器會出現假死

然后我們執行setTimeout方式的方法,setTImeout的方式,我們每次只操作數組里面的一個對象,并且在每次操作之間,設置了100ms的延時,供js引擎執行主干的代碼,因此,很明顯,執行的效果非常棒!

我們看到,不僅瀏覽器的標題欄不會轉菊花了,控制臺也很快就打印出 我們在代碼最后面打印的語句,說明主干程序已經走完,數組的處理則定時執行著。
通過這樣的優化,我們的程序給用戶的體驗提示了許多,當然,這里只是書中介紹的一種方法,我相信還有很多其他實現方式,比如我現在可以想到的就有promise,有機會我會補充一下,大家也可以暢所欲言,看看有什么其他更好的方法來對付這種循環耗時操作!
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持武林網!
新聞熱點
疑難解答