国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

setTimeout和setInterval

SnaiLiu / 1138人閱讀

摘要:一個(gè)頁(yè)面在瀏覽器顯示出來(lái)至少需要個(gè)線程,分別是引擎,渲染,事件觸發(fā)。其中事件觸發(fā)是獨(dú)立于其他個(gè)執(zhí)行的,而和是相互排斥的,也就是說(shuō)同一個(gè)時(shí)間二者只有一個(gè)在工作。

作為DOM本身十分重要的2個(gè)異步執(zhí)行函數(shù),初學(xué)者感覺(jué)這個(gè)很不好理解,我簡(jiǎn)單寫一寫我的理解

setTimeout (func, millisec);
setInterval(func, millisec);

這兩個(gè)方法在形式看起來(lái)很相似,第一個(gè)參數(shù)是異步執(zhí)行的函數(shù)(用字符串表示的代碼也可以,不過(guò)很少這樣用),第二個(gè)參數(shù)是時(shí)間(ms)。但其實(shí)這兩個(gè)函數(shù)還是有很大區(qū)別的

說(shuō)的通俗一點(diǎn),setTimeout()讓電腦一定時(shí)間以后再執(zhí)行一段代碼,執(zhí)行完了就拉倒,例如下面這段代碼:

setTimeout("alert("5 seconds!")", 5000); //5秒后彈出提示框 

再看看setInterval(),不同的在于每過(guò)一段時(shí)間會(huì)重復(fù)執(zhí)行一段代碼。比如在瀏覽器中輸出一個(gè)時(shí)間,每一秒變化一下。

var clk = document.getElementById("clk"); //clk是一個(gè)div
setInterval(function(){
  var t = new Date();
  clk.innerHTML= t;
}, 200);
//每隔200ms顯示一次時(shí)間,200ms會(huì)看著比1000ms更穩(wěn)定一些

運(yùn)行上面這個(gè)代碼,如果你得到的時(shí)間不準(zhǔn)確,那一定是你的電腦時(shí)間錯(cuò)了。
好了,總結(jié)一下:

setTimeout(func, m); //m毫秒后執(zhí)行函數(shù)func,只執(zhí)行一次(下文會(huì)講怎么讓它中止)
setInterval(func, m); //每隔m毫秒執(zhí)行函數(shù)func,一直執(zhí)行下去(下文會(huì)講怎么讓它停下來(lái))

對(duì)于setInterval()的用途可能還比較好理解,但是對(duì)于setTimeout(),這里有一個(gè)問(wèn)題——我們?yōu)槭裁匆屢欢未a過(guò)一段時(shí)間在執(zhí)行?

這里就產(chǎn)生了一個(gè)很重要的概念,在本文一開(kāi)始就提到過(guò)——異步!什么是異步?
舉個(gè)通俗一點(diǎn)的例子:比如現(xiàn)在有燒水和擦桌子兩件事,如果你一定要用熱水擦桌子,那你就必須先等著水開(kāi)了,才能擦桌子,這個(gè)就是同步;如果你不在乎用什么水擦桌子,那一般人都會(huì)先燒水,在燒水的同時(shí)就開(kāi)始擦桌子了,這個(gè)就是異步。

對(duì)于計(jì)算機(jī)而言,這個(gè)邏輯和正常生活不一樣:同時(shí)執(zhí)行就是異步,先后執(zhí)行就是同步!當(dāng)然這是一種簡(jiǎn)單的理解,并不嚴(yán)謹(jǐn),畢竟在計(jì)算機(jī)內(nèi)部計(jì)時(shí)器脈沖、操作系統(tǒng)進(jìn)程、網(wǎng)絡(luò)通信中都有同步和異步的概念。

有了異步執(zhí)行這個(gè)概念,那小編可以負(fù)責(zé)的說(shuō)setTimeout()setInterval()都是異步執(zhí)行的。其實(shí)2015年出的ES6在異步這里下了很大的功夫,提出了async function(){}Promise對(duì)象、Generator函數(shù)、Object.observe函數(shù)等很多新概念,不過(guò)這里不談這些概念,但理解這些異步概念絕不能像這篇文章里面簡(jiǎn)單粗暴!!!

好了現(xiàn)在可以回答上面那個(gè)問(wèn)題了,我們之所以會(huì)用到setTimeout()setInterval()更多還是為了異步執(zhí)行代碼,以此提高代碼的執(zhí)行速度。到此這兩個(gè)方法的就講完了。。。等等!!!方法?方法會(huì)不會(huì)有返回值呀!
沒(méi)錯(cuò),這兩個(gè)函數(shù)都有返回值,至于這個(gè)值是個(gè)什么并不重要,我們只需要知道這個(gè)值能干什么,我們給上面的那段代碼添點(diǎn)東西:

var clk = document.getElementById("clk"); //clk是一個(gè)div
var time = setInterval(function(){
  var t = new Date()
  clk.innerHTML= t;
}, 200);

var btn = document.getElementById("btn"); //btn是一個(gè)按鈕
btn.onclick = function(){
  clearInterval(time);
};

這段代碼我們獲得了setInterval() 的返回值,把返回值傳給了clearInterval()方法,這樣實(shí)現(xiàn)了點(diǎn)擊按鈕結(jié)束的對(duì)應(yīng)setInterval()的反復(fù)調(diào)用,終于它可以停下來(lái)了。

同樣的方法,利用clearTimeout() 方法可取消由 setTimeout() 函數(shù)定義的異步操作,我們?nèi)绶ㄅ谥频玫揭粋€(gè)取消延遲事件的按鈕(當(dāng)然,如果這個(gè)事件已經(jīng)執(zhí)行了再點(diǎn)這個(gè)按鈕就沒(méi)意義了):

var alt = setTimeout("alert("5 seconds!")", 5000); //5秒后彈出提示框
var btn = document.getElementById("btn"); //btn是一個(gè)按鈕
btn.onclick = function(){
  clearTimeout(alt);
};

如果用setIntervalsetTimeout調(diào)用的函數(shù)是一個(gè)有參數(shù)的函數(shù)怎么辦?

function f(a, b){/*...*/}
var num = 2;
setTimeout("f(num, 3)", 1000);  //第一種方法
setTimeout(function(){fun(num, 3);}, 1000);  //第二種方法

這一下,setTimeout()setInterval()已經(jīng)理解了,看它們相似點(diǎn)其實(shí)也不少,否則怎么會(huì)容易被搞混呢?其實(shí)我們可以使用setTimeout()實(shí)現(xiàn)setInterval()的功能,就像下面一段代碼:

function mySetInterval(code, ms){
  if(typeof code === "string")  //不要忘了第一個(gè)參數(shù)可以是字符串
    eval(code);
  else if(typeof code === "function")
    code();
  else throw new Error("code cannot be run");  //當(dāng)?shù)谝粋€(gè)參數(shù)傳入不是字符串或函數(shù)時(shí)報(bào)錯(cuò)
  setTimeout(function(){
    mySetInterval(code, ms);  //遞歸調(diào)用
  },ms);
}
mySetInterval("document.write("helloWorld!
")", 1000);//調(diào)用方法不變,第一個(gè)參數(shù)也可以是函數(shù)

這里值得強(qiáng)調(diào)的是eval()并不是什么好東西,它在全局運(yùn)行,對(duì)字符串并不能有效檢查(會(huì)讓JSLint失效),還會(huì)調(diào)用編譯器降低效率,同時(shí)帶來(lái)安全隱患。所以盡量不要用eval(),也不要給setTimeoutsetInterval傳入字符串,因?yàn)橄到y(tǒng)也是用eval實(shí)現(xiàn)這個(gè)功能的。
這段代碼只是用這樣一種方式表示setTimeout()setInterval()的關(guān)系,便于讀者理解。并不表示這樣做有什么好,更不表示編譯器也這么實(shí)現(xiàn)setInterval(),因?yàn)檫@樣的遞歸效率不高占用資源卻不少,而且它沒(méi)法停止。

如果你已經(jīng)掌握了上面的內(nèi)容,那么下面可以更深入的理解一下異步了。

以setTimeout為例:

//alert(1);
//setTimeout("alert(2)", 0);
//alert(3);
//alert(3);

上面這段代碼會(huì)如何輸出呢?實(shí)際輸出是:1 -> 3 -> 3 ->2,為什么會(huì)這樣,難道setTimeout(func, 0)不是立即執(zhí)行?沒(méi)錯(cuò)。想理解這個(gè)問(wèn)題,必須簡(jiǎn)單理解瀏覽器是如何處理異步函數(shù)的。

一個(gè)頁(yè)面在瀏覽器顯示出來(lái)至少需要3個(gè)線程,分別是js引擎,GUI渲染,事件觸發(fā)。其中事件觸發(fā)是獨(dú)立于其他2個(gè)執(zhí)行的,而js和GUI是相互排斥的,也就是說(shuō)同一個(gè)時(shí)間二者只有一個(gè)在工作。好了,這說(shuō)明js引擎是單線程執(zhí)行的,當(dāng)?shù)诙械?b>setTimeout執(zhí)行以后,js引擎把func(第一個(gè)參數(shù))放入異步隊(duì)列(瀏覽器再開(kāi)一個(gè)線程),然后繼續(xù)向下執(zhí)行,此后,當(dāng)js引擎空閑下來(lái)才會(huì)把異步執(zhí)行的結(jié)果插入原來(lái)js線程中。是不是這樣呢,我們讓代碼說(shuō)話:

    var finish = true;
    setTimeout(function(){
        finish = false;  //1s后,改變isEnd的值
    }, 0);
    while(finish);
    alert("finished");  //永遠(yuǎn)不會(huì)執(zhí)行

上方這段代碼是個(gè)死循環(huán),就因?yàn)閖s引擎不能空閑下來(lái),異步函數(shù)也就沒(méi)有執(zhí)行。下面這個(gè)實(shí)際問(wèn)題可以很好的理解這個(gè):




  
  



  
    
click "first" button to calculate.

click "second" button to calculate.

我們用了一很大的循環(huán)模擬一個(gè)耗費(fèi)時(shí)間的計(jì)算。

分析一下:第一個(gè)按鈕看不到calculating。由于js引擎的事件處理也是異步的,而for循環(huán)是同步的,設(shè)置文字為calculating的語(yǔ)句被放在了for循環(huán)結(jié)束,因?yàn)橹挥写藭r(shí)js才有空閑處理異步隊(duì)列,for結(jié)束了以后,文字被設(shè)置為calculating,繼而變?yōu)镈one,所以我們看不到這個(gè)過(guò)程了,在代碼中debugger的位置停一下,這個(gè)過(guò)程就清晰的呈現(xiàn)了出來(lái)。

為了解決這個(gè)問(wèn)題,第二個(gè)按鈕引入了setTimeout這樣,異步事件click執(zhí)行,函數(shù)內(nèi)第一個(gè)語(yǔ)句被送入隊(duì)列,而后setTimeout里那個(gè)匿名函數(shù)被送入隊(duì)列,此時(shí)js引擎有空閑,于是輸出calculating,異步隊(duì)列移動(dòng),繼續(xù)執(zhí)行calc,這樣就是我們想看到的結(jié)果了。

不足之處請(qǐng)多指點(diǎn)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/97594.html

相關(guān)文章

  • process.nextTick() 、setTimeout()、setInterval() 運(yùn)行機(jī)

    摘要:注意如果主邏輯的代碼執(zhí)行時(shí)間已經(jīng)超過(guò)了第二個(gè)參數(shù)設(shè)置的時(shí)間,那么等運(yùn)行到該回調(diào)函數(shù)時(shí),它會(huì)忽略掉這個(gè)時(shí)間,并立即執(zhí)行。如果某一個(gè)進(jìn)行大量的計(jì)算,那么它就會(huì)阻塞在當(dāng)前的回調(diào)函數(shù)中,等待該計(jì)算完成后,再執(zhí)行下一個(gè)的回調(diào)函數(shù)。 setTimeout() ? JavaScript是一個(gè)單線程的語(yǔ)言,也就是說(shuō)它同一時(shí)間只能執(zhí)行一段代碼,接下來(lái)我們通過(guò)兩個(gè)例子說(shuō)明一下單線程語(yǔ)言和多線程語(yǔ)言的...

    lscho 評(píng)論0 收藏0
  • setTimeoutsetInterval的使用

    摘要:不過(guò)兩者各有各的應(yīng)用場(chǎng)景。方法實(shí)際上,和的語(yǔ)法相同。這意味著如果函數(shù)的主體部分需要秒鐘執(zhí)行完,那么整個(gè)函數(shù)則要每秒鐘才執(zhí)行一次。不過(guò)還是有辦法可以終止和函數(shù)的執(zhí)行。 var intervalProcess = setInterval(alert(GOAL!), 3000); 這個(gè)變量命名可以在實(shí)際代碼中采用 這兩個(gè)方法都可以用來(lái)實(shí)現(xiàn)在一個(gè)固定時(shí)間段之后去執(zhí)行JavaScript。不過(guò)...

    noONE 評(píng)論0 收藏0
  • JS忍者秘籍中的定時(shí)器機(jī)制詳解

    摘要:設(shè)置和清除定時(shí)器直接引用忍者秘籍中的圖片注意定時(shí)器的時(shí)間間隔設(shè)為,也會(huì)有幾毫秒的延遲。以上參考資料忍者秘籍第章馴服線程和定時(shí)器 showImg(https://segmentfault.com/img/remote/1460000015353524?w=1024&h=681); 前言 前段時(shí)間剛看完《JS忍者秘籍》,雖說(shuō)是15年出版的,有些東西是過(guò)時(shí)了,但像對(duì)原型鏈、閉包、正則、定時(shí)器...

    keelii 評(píng)論0 收藏0
  • 定時(shí)器

    摘要:提供定時(shí)執(zhí)行代碼的功能,叫做定時(shí)器,主要由和這兩個(gè)函數(shù)來(lái)完成。它返回一個(gè)整數(shù),表示定時(shí)器的編號(hào),以后可以用來(lái)取消這個(gè)定時(shí)器。上面代碼中,回調(diào)函數(shù)不會(huì)再執(zhí)行了,因?yàn)閮蓚€(gè)定時(shí)器都被取消了。 JavaScript 提供定時(shí)執(zhí)行代碼的功能,叫做定時(shí)器(timer),主要由setTimeout()和setInterval()這兩個(gè)函數(shù)來(lái)完成。它們向任務(wù)隊(duì)列添加定時(shí)任務(wù)。 setTimeout()...

    Nino 評(píng)論0 收藏0
  • js計(jì)數(shù)器方法setInterval()、clearInterval()、setTimeout()

    摘要:方法描述周期性地調(diào)用一個(gè)函數(shù)或者執(zhí)行一段代碼。方法可取消由方法設(shè)置的。語(yǔ)法詳解是該延時(shí)操作的數(shù)字此隨后可以用來(lái)作為方法的參數(shù)。需要注意的是,不支持第一種語(yǔ)法中向延遲函數(shù)傳遞額外參數(shù)的功能。該值標(biāo)識(shí)要取消的延遲執(zhí)行代碼塊。 方法 描述 setInterval 周期性地調(diào)用一個(gè)函數(shù)(function)或者執(zhí)行一段代碼。 clearInterval 取消掉用setI...

    keithxiaoy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<