摘要:這里是結論,將是更驚艷的那一個。瀏覽器隔一段時間像服務器發送一個請求,詢問這里有沒有需要更新的消息。在響應回來時,才會繼續發出第二個請求。但是,顯然的,這對我們要做的事來說并不算是什么問題。
我們都知道的是setTimout是用來延遲一個簡單的動作的,然而,setInterval的目的是用來重復執行某個動作的。
然后,以上只是一半的事實。因為如果一個函數需要在一個間隔時間內重復的執行,你也可以輕松的使用 setTimeout 設定延遲時間,被延遲執行的函數再進行自調用以此實現循環。
所以,這里有2種方法做同樣的事
一個用setInterval
var doStuff = function () { // Do stuff }; setInterval(doStuff, 1000);
一個用setTimeout
var doStuff = function () { // DoStuff setTimeout(doStuff, 1000); }; setTimeout(doStuff, 1000);
// 如果你想立即執行函數,可以這樣寫 var doStuff = function () { setTimeout(doStuff, 1000); } doStuff();
// 或者,更酷的方式,使用立即執行函數 (function doStuff () { // Do Stuff setTimeout(doStuff, 1000); }())
這必然導致下面兩個問題
問題:setInterval和self-invoking setTimeout-loops是可以互相替換的嗎?
答案:不,當然不行。它們之間有著很細微的區別,但是如果想寫出好的代碼,這些細微的區別便是你想知道的事。
當然,接下我將會訴說的,第一,我將告訴你,我們通常會遇到什么樣的問題,第二,我將開始介紹它們之間細微的區別,這些區別將讓我們從這兩個選擇中選出更具吸引力的那個一,第三,我將告訴你其實根本不用關心另一個。然后。這里是結論,setTimeout將是更驚艷的那一個。接下來我將一點一點解釋。
進程堵塞首先:如果你試著重復調用的函數并不會化太多的時間來跑,那么將不會有任何問題。即使如此,被調用的函數依然會出現2中不同的情況:它既可以在CPU上高集中的運行腳本,或者它也可以在腳本流外先發出一個命令,并等待結果的到來。
我們主要研究先看第二種情況。典型的便是ajax回調:你的腳本并不會等待服務器的響應,它會自己執行到最后,并讓回調函數來監聽ajax響應。
現在,一些網站想要你保持實時更新,像Gmail,當你獲得一封新的郵件時便會刷新你的郵箱。這里服務端有新消息時便實時通知瀏覽器端的技術,通常叫做ajax輪詢。瀏覽器隔一段時間像服務器發送一個請求,詢問這里有沒有需要更新的消息。
你也許會想,你很擅長使用setInterval
// 不要這樣做 var pollServerForNewMail = function () { $.getJSON("/poll_newmail.php", function (response) { if (response.newMail) { alert( "New mail. At last. You made me walk all the way to the server and back every " + "second for this, so if this isn"t life-or-death, you got another thing coming." ); } }); }; setInterval(pollServerForNewMail, 1000);
其實像上面那樣寫并不好。因為請求發送出去到回來是需要時間的,但是這段時間誰能保證會比你設置的間隔時間要短呢?
一個典型的初學者的錯誤,會想將輪詢的間隔時間設置的長一點也許可以解決這個問題。然后,事實是,無論你的間隔時間設的是多少,它依然有可能比,ajax響應的時間短。也就是說,有可能會發生,第一個請求還沒回來的情況下,第二請求又已經發出去了。而你需要的是兩個請求之間有呼吸的空間,而setTimeout便可以解決這個問題。
(function pollServerForNewMail() { $.getJSON("/poll_newmail.php", function (response) { if (response.newMail) { alert( "You have received a letter, good sir. " + "I will have a quick lie-down and be on my way shortly." ); } setTimeout(pollServerForMail, 1000); }); }());
在第一次發出請求,服務器響應之前,不會發生任何事。在響應回來時,才會繼續發出第二個請求。當然,這也就意味著,兩個輪詢之間的時間超過了1秒,這也依賴于各種各樣的因素,像網速和服務器的響應速度等。但是,顯然的,這對我們要做的事來說并不算是什么問題。
例子這里有兩個例子來更好的進行說明。
var timesRun = 0; var startTime = new Date().getTime(); var doStuff = function () { var now = new Date().getTime(); // 只跑5次 if (++timesRun == 5) clearInterval(timer); console.log("Action " + timesRun + " started " + (now - startTime) + "ms after script start"); // Waste some time for (var i = 0; i < 100000; i++) { document.getElementById("unobtanium"); } console.log("and took " + (new Date().getTime() - now) + "ms to run."); }; var timer = setInterval(doStuff, 1000);
下面是結果
Action 1 started 1000ms after script start and took 8ms to run. Action 2 started 2000ms after script start and took 8ms to run. Action 3 started 3004ms after script start and took 6ms to run. Action 4 started 4002ms after script start and took 6ms to run. Action 5 started 5000ms after script start and took 6ms to run.
這里并沒有多大的意外。這段代碼中間的循環花了一點時間,但是setInterval依然很嚴格的執行了它的計劃。在一秒的間隔之間,開始時間之間并沒有一點空隙。
現在是setTimeout-loop的例子
var timesRun = 0; var startTime = new Date().getTime(); var doStuff = function () { var now = new Date().getTime(); console.log("Action " + (timesRun + 1) + " started " + (now - startTime) + "ms after script start"); // Waste some time for (var i = 0; i < 100000; i++) { document.getElementById("unobtanium"); } console.log("and took " + (new Date().getTime() - now) + "ms to run."); // Run only 5 times if (++timesRun < 5) { setTimeout(doStuff, 1000); } }; setTimeout(doStuff, 1000);
輸出結果
Action 1 started 1010ms after script start and took 8ms to run. Action 2 started 2021ms after script start and took 8ms to run. Action 3 started 3031ms after script start and took 5ms to run. Action 4 started 4037ms after script start and took 6ms to run. Action 5 started 5043ms after script start and took 6ms to run.
這里也并沒有太多的意外。我們已經知道setTimeout-loop并不會嚴格的執行計劃,而是在函數下一次調用之前,會給函數它足夠的時間執行它里面的代碼。
結論不要使用setInterval,如果你在乎你的時間。setTimeout-loop可以給你足夠的時間控制你的腳本和回調,
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80888.html
摘要:關于這部分有嚴格的文字定義,但本文的目的是用最小的學習成本徹底弄懂執行機制,所以同步和異步任務分別進入不同的執行場所,同步的進入主線程,異步的進入并注冊函數。宏任務微任務第三輪事件循環宏任務執行結束,執行兩個微任務和。 不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發工作,我們經常會遇到這樣的情況:給定的幾行代碼,我們需要知道其輸出內容和順序。 因為javascr...
摘要:所以,我們可以將理解為計時結束是執行任務的必要條件,但是不是任務是否執行的決定性因素。的意思是,必須超過毫秒后,才允許執行。 先來回答一下下面這個問題:對于 setTimeout(function() { console.log(timeout) }, 1000) 這一行代碼,你從哪里可以找到 setTimeout 的源代碼(同樣的問題還會是你從哪里可以看到 setInterval 的...
摘要:事件完成,回調函數進入。主線程從讀取回調函數并執行。終于執行完了,終于從進入了主線程執行。遇到,立即執行。宏任務微任務第三輪事件循環宏任務執行結束,執行兩個微任務和。事件循環事件循環是實現異步的一種方法,也是的執行機制。 本文的目的就是要保證你徹底弄懂javascript的執行機制,如果讀完本文還不懂,可以揍我。不論你是javascript新手還是老鳥,不論是面試求職,還是日常開發工作...
摘要:事件完成,回調函數進入。我們來分析一段較復雜的代碼,看看你是否真的掌握了的執行機制第一輪事件循環流程分析如下整體作為第一個宏任務進入主線程,遇到,輸出。宏任務微任務第三輪事件循環宏任務執行結束,執行兩個微任務和。 關于JavaScript 首先js是單線程的,執行任務肯定是一個接著一個。在最新的html5中提出了web-worker,但是JavaScript是單線程這一核心沒有改變,一...
摘要:設置和清除定時器直接引用忍者秘籍中的圖片注意定時器的時間間隔設為,也會有幾毫秒的延遲。以上參考資料忍者秘籍第章馴服線程和定時器 showImg(https://segmentfault.com/img/remote/1460000015353524?w=1024&h=681); 前言 前段時間剛看完《JS忍者秘籍》,雖說是15年出版的,有些東西是過時了,但像對原型鏈、閉包、正則、定時器...
閱讀 2101·2023-04-25 17:23
閱讀 2919·2021-11-17 09:33
閱讀 2513·2021-08-21 14:09
閱讀 3579·2019-08-30 15:56
閱讀 2605·2019-08-30 15:54
閱讀 1623·2019-08-30 15:53
閱讀 2126·2019-08-29 13:53
閱讀 1141·2019-08-29 12:31