摘要:大多數(shù)瀏覽器并沒有精確到毫秒級別的觸發(fā)事件,例如,我們設(shè)定某個函數(shù)在毫秒后執(zhí)行,在老版本的中,這個函數(shù)至少會在毫秒以后執(zhí)行。三實戰(zhàn)光說不練假把式,現(xiàn)在我們就用上面介紹的三種定時器完成進度條的效果。
一.常見定時器
我們常見的定時器有以下兩種 1. window.setTimeout 用于在指定的毫秒數(shù)后執(zhí)行某段既定的代碼 2. window.setInterval 用于每隔一段毫秒數(shù)重復(fù)執(zhí)行既定的代碼 這兩個方法都可以通過手工設(shè)置時間來設(shè)定是多少毫秒后執(zhí)行這段代碼,或者是每隔多少毫秒執(zhí)行這段代碼。
雖然我們期待瀏覽器按照我們設(shè)定的時間精確的執(zhí)行代碼,但是js卻不能保證代碼能恰好在那個時間點被運行,原因有兩個。
大多數(shù)瀏覽器并沒有精確到毫秒級別的觸發(fā)事件,例如,我們設(shè)定某個函數(shù)在3毫秒后執(zhí)行,在老版本的IE中,這個函數(shù)至少會在15毫秒以后執(zhí)行。而在現(xiàn)代瀏覽器中,這個數(shù)值會短一點,但時間差一般也會超過1毫秒。
第二個原因與js的運行機制有關(guān),具體見JavaScript 運行機制詳解:再談Event Loop.簡單來說,就是js是一個單線程的解釋器,一段時間只能執(zhí)行一段代碼,所以運行時分為主線程和任務(wù)隊列兩部分。而我們在定時器中設(shè)置的時間,僅代表1000毫秒后把這個任務(wù)插入到任務(wù)隊列中,而此時必須要等到主線程的代碼執(zhí)行完畢,才能執(zhí)行任務(wù)隊列中的定時器的任務(wù)(在任務(wù)隊列中也有調(diào)度,不一定第一個執(zhí)行當前任務(wù)),因此時間是無法保證的。
二、requestAnimationFrame那有沒有時間準確的定時器呢?有一種選擇是requestAnimationFrame. 示例如下:
function animateMe(){ requestAnimationFrame(function(){ console.log(new Date()); animateMe(); }) } animateMe();
這個api的原理是在由系統(tǒng)來決定回調(diào)函數(shù)的執(zhí)行時機,在每一次系統(tǒng)繪制之前,會主動調(diào)用requestAnimationFrame中的回調(diào)函數(shù),而頻率也緊緊跟隨瀏覽器的刷新頻率。比如一般電腦的刷新頻率通常為60Hz,即一秒鐘重繪60次,那么回調(diào)函數(shù)就等于1000/60=16.7毫秒被執(zhí)行一次,而如果刷新頻率變?yōu)?5Hz,那么這個時間就變?yōu)?000/75=13.3毫秒被執(zhí)行一次。這樣能保證回調(diào)函數(shù)在每一次繪制的間隔時間內(nèi)只被執(zhí)行一次,因此它的時間是可靠的。
三、實戰(zhàn)光說不練假把式,現(xiàn)在我們就用上面介紹的三種定時器完成進度條的效果。
1.setInterval
var timer; $(".runBtn").click(function(){ clearInterval(timer); $("#bar").width(0); timer = setInterval(function(){ if($("#bar").width() < 500){ $("#bar").width($("#bar").width()+5); $("#bar").text($("#bar").width()/5+"%"); }else{ clearInterval(timer); } },16); });
點此預(yù)覽效果
2.setTimeout
var timer; $(".runBtn").click(function(){ clearTimeout(timer); $("#bar").width(0); timer = setTimeout(function fn(){ if($("#bar").width() < 500){ $("#bar").width($("#bar").width()+5); $("#bar").text($("#bar").width()/5+"%"); timer = setTimeout(fn,16); }else{ clearTimeout(timer); } },16); });
點此預(yù)覽效果
3.requestAnimationFrame
var timer; $(".runBtn").click(function(){ cancelAnimationFrame(timer); $("#bar").width(0); timer = requestAnimationFrame(function fn(){ if($("#bar").width() < 500){ $("#bar").width($("#bar").width()+5); $("#bar").text($("#bar").width()/5+"%"); requestAnimationFrame(fn); }else{ cancelAnimationFrame(timer); } }); });
點此預(yù)覽效果
四、最后文章都來自本人的總結(jié),難免有些紕漏,歡迎大家指正。一起學(xué)習(xí),一起進步。如果覺得不錯,歡迎點贊收藏嚶嚶嚶~~~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107692.html
摘要:定時器方法相關(guān)方法有四種。返回值返回值是一個正整數(shù),表示定時器的編號。這個值可以傳遞給來取消該定時器。使用方法很簡單只有一個參數(shù),該參數(shù)為您要取消定時器的標識符。用法很簡單當代碼運行到這行的時候,會取消所設(shè)置的定時器。 簡單介紹在JavaScript中定時器有兩個 setInterval() 與 setTime...
摘要:由于引擎同一時間只執(zhí)行一段代碼這是由單線程的性質(zhì)決定的,所以每個代碼塊阻塞了其它異步事件的進行。這意味著瀏覽器將等待著一個新的異步事件發(fā)生。異步的任務(wù)執(zhí)行的順序是不固定的,主要看返回的速度。 我們經(jīng)常說JS是單線程的,比如node.js研討會上大家都說JS的特色之一是單線程的,這樣使JS更簡單明了,可是大家真的理解所謂JS的單線程機制嗎?單線程時,基于事件的異步機制又該當如何,這些知識...
摘要:當間隔時間設(shè)置較小時,將會導(dǎo)致回調(diào)函數(shù)堆積。處理可能阻塞的代碼最簡單且最可控的方式就是在回調(diào)函數(shù)內(nèi)部使用函數(shù)。但是很明顯,由于指定最大值的限制,還會有定時器沒有被清除掉。另外,盡量避免使用函數(shù),從而避免可能導(dǎo)致的回調(diào)函數(shù)堆積現(xiàn)象。 由于 Javascript 是異步的,因此我們可以通過 setTimeout 和 setInterval 函數(shù)來指定特定時間執(zhí)行代碼。 function ...
摘要:說到中的定時器,我們肯定會想到和這兩個函數(shù)。第一個回調(diào)一執(zhí)行,又開啟了第二個,這個定時器也是期望延時之后能夠執(zhí)行它的回調(diào)函數(shù)。可以用下面的圖來概括總結(jié)上面對定時器執(zhí)行原理進行了簡要的分析,希望能夠幫助我們更深入的理解。 說到 javascript 中的定時器,我們肯定會想到 setTimeout() 和 setInterval() 這兩個函數(shù)。本文將從 事件循環(huán)(Event Loop)...
摘要:提出標準,允許腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作。所以,這個新標準并沒有改變單線程的本質(zhì)。事件循環(huán)主線程線程只會做一件事,就是從消息隊列里面取消息執(zhí)行消息,再取消息再執(zhí)行。工作線程是生產(chǎn)者,主線程是消費者。 最近項目中遇到了一個場景,其實很常見,就是定時獲取接口刷新數(shù)據(jù)。那么問題來了,假設(shè)我設(shè)置的定時時間為1s,而數(shù)據(jù)接口返回大于1s,應(yīng)該用同步阻塞還是異步?我們...
閱讀 1438·2023-04-25 16:31
閱讀 2040·2021-11-24 10:33
閱讀 2746·2021-09-23 11:33
閱讀 2528·2021-09-23 11:31
閱讀 2900·2021-09-08 09:45
閱讀 2336·2021-09-06 15:02
閱讀 2647·2019-08-30 14:21
閱讀 2313·2019-08-30 12:56