摘要:所以其實(shí)和所謂的異步調(diào)用事實(shí)上是通過(guò)將代碼段插入到代碼的執(zhí)行隊(duì)列中實(shí)現(xiàn)的。當(dāng)執(zhí)行和的時(shí)候,會(huì)根據(jù)你設(shè)定的時(shí)間準(zhǔn)確地找到代碼的插入點(diǎn)。綜上所述,其實(shí)終歸是單線程產(chǎn)物。無(wú)論如何異步都不可能突破單線程這個(gè)障礙。
發(fā)表過(guò)一片博客《跟著我用JavaScript寫(xiě)計(jì)時(shí)器》,比較基礎(chǔ).....有網(wǎng)友說(shuō)應(yīng)該寫(xiě)一下setTimeout的原理和機(jī)制,嗯,今天就來(lái)寫(xiě)一下吧:
直奔主題:setTimeout和setInterval是如何工作的呢?我們知道,js是單線程執(zhí)行的(單線程j就是說(shuō)在程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來(lái),前面的必須處理好,后面的才會(huì)執(zhí)行)。所以其實(shí)setTimeout和setInterval所謂的“異步調(diào)用”事實(shí)上是通過(guò)將代碼段插入到代碼的執(zhí)行隊(duì)列中實(shí)現(xiàn)的。
而如何計(jì)算插入的時(shí)間點(diǎn)呢?自然是要用到我們所說(shuō)的timer,也就是計(jì)時(shí)器。當(dāng)執(zhí)行setTimeout和setInterval的時(shí)候,timer會(huì)根據(jù)你設(shè)定的時(shí)間“準(zhǔn)確”地找到代碼的插入點(diǎn)。當(dāng)隊(duì)列“正常”地執(zhí)行到插入點(diǎn)時(shí),就觸發(fā)timer callback,也就是我們?cè)O(shè)定的回調(diào)函數(shù):
function fn() { /* here is some codes */ alert("javascript"); setTimeout(function() {alert("ok!")},1000); } onload=fn;
上面這個(gè)例子就是我們通常的用法,應(yīng)該容易理解。可是,timer真的能那么準(zhǔn)確么?代碼隊(duì)列的執(zhí)行真的能那么正常么?
還記得嗎?重新認(rèn)識(shí)所謂的“異步”剛剛已經(jīng)知道,事實(shí)上setTimeout和setInterval只是簡(jiǎn)簡(jiǎn)單單地通過(guò)插入代碼到代碼隊(duì)列來(lái)實(shí)現(xiàn)代碼的延遲執(zhí)行(或者說(shuō)異步執(zhí)行)。但是事實(shí)上所謂的異步只是一個(gè)假象——它同樣運(yùn)行在一個(gè)線程上! 始終是單線程!
那么問(wèn)題就來(lái)了,要是在代碼插入點(diǎn)前的代碼執(zhí)行時(shí)間超過(guò)了傳入setTimeout或setInterval的設(shè)定時(shí)間會(huì)怎樣呢?讓我們來(lái)看看這段代碼:
function fn() { setTimeout(function(){alert("can you see me?");},1000); while(true) {} }
你覺(jué)得這段代碼的執(zhí)行結(jié)果是什么呢?答案是,alert永遠(yuǎn)不會(huì)出現(xiàn)。
這是為什么呢?因?yàn)椋瑆hile這段代碼沒(méi)有執(zhí)行完(如圖,瀏覽器一直在解析while的代碼),所以插入在后面的代碼便永遠(yuǎn)不會(huì)執(zhí)行。
綜上所述,其實(shí)JS終歸是單線程產(chǎn)物。無(wú)論如何“異步”都不可能突破單線程這個(gè)障礙。所以許多的“異步調(diào)用”(包括Ajax)事實(shí)上也只是“偽異步”而已。只要理解了這么一個(gè)概念,也許理解setTimeout和setInterval也就不難了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/49648.html
摘要:所以其實(shí)和所謂的異步調(diào)用事實(shí)上是通過(guò)將代碼段插入到代碼的執(zhí)行隊(duì)列中實(shí)現(xiàn)的。當(dāng)執(zhí)行和的時(shí)候,會(huì)根據(jù)你設(shè)定的時(shí)間準(zhǔn)確地找到代碼的插入點(diǎn)。綜上所述,其實(shí)終歸是單線程產(chǎn)物。無(wú)論如何異步都不可能突破單線程這個(gè)障礙。 發(fā)表過(guò)一片博客《跟著我用JavaScript寫(xiě)計(jì)時(shí)器》,比較基礎(chǔ).....有網(wǎng)友說(shuō)應(yīng)該寫(xiě)一下setTimeout的原理和機(jī)制,嗯,今天就來(lái)寫(xiě)一下吧: 直奔主題:setTimeout和...
摘要:由于引擎同一時(shí)間只執(zhí)行一段代碼這是由單線程的性質(zhì)決定的,所以每個(gè)代碼塊阻塞了其它異步事件的進(jìn)行。這意味著瀏覽器將等待著一個(gè)新的異步事件發(fā)生。異步的任務(wù)執(zhí)行的順序是不固定的,主要看返回的速度。 我們經(jīng)常說(shuō)JS是單線程的,比如node.js研討會(huì)上大家都說(shuō)JS的特色之一是單線程的,這樣使JS更簡(jiǎn)單明了,可是大家真的理解所謂JS的單線程機(jī)制嗎?單線程時(shí),基于事件的異步機(jī)制又該當(dāng)如何,這些知識(shí)...
摘要:主線程會(huì)暫時(shí)存儲(chǔ)等異步操作,直接向下執(zhí)行,當(dāng)某個(gè)異步事件觸發(fā)時(shí),再通知主線程執(zhí)行相應(yīng)的回調(diào)函數(shù),通過(guò)這種機(jī)制,避免了單線程中異步操作耗時(shí)對(duì)后續(xù)任務(wù)的影響。 背景 在研究js的異步的實(shí)現(xiàn)方式的時(shí)候,發(fā)現(xiàn)了JavaScript 中的 macrotask 和 microtask 的概念。在查閱了一番資料之后,對(duì)其中的執(zhí)行機(jī)制有所了解,下面整理出來(lái),希望可以幫助更多人。 先了解一下js的任務(wù)執(zhí)...
摘要:提出標(biāo)準(zhǔn),允許腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作。所以,這個(gè)新標(biāo)準(zhǔn)并沒(méi)有改變單線程的本質(zhì)。事件循環(huán)主線程線程只會(huì)做一件事,就是從消息隊(duì)列里面取消息執(zhí)行消息,再取消息再執(zhí)行。工作線程是生產(chǎn)者,主線程是消費(fèi)者。 最近項(xiàng)目中遇到了一個(gè)場(chǎng)景,其實(shí)很常見(jiàn),就是定時(shí)獲取接口刷新數(shù)據(jù)。那么問(wèn)題來(lái)了,假設(shè)我設(shè)置的定時(shí)時(shí)間為1s,而數(shù)據(jù)接口返回大于1s,應(yīng)該用同步阻塞還是異步?我們...
摘要:圖片轉(zhuǎn)引自的演講和兩個(gè)定時(shí)器中回調(diào)的執(zhí)行邏輯便是典型的機(jī)制。異步編程關(guān)于異步編程我的理解是,在執(zhí)行環(huán)境所提供的異步機(jī)制之上,在應(yīng)用編碼層面上實(shí)現(xiàn)整體流程控制的異步風(fēng)格。 問(wèn)題背景 在一次開(kāi)發(fā)任務(wù)中,需要實(shí)現(xiàn)如下一個(gè)餅狀圖動(dòng)畫(huà),基于canvas進(jìn)行繪圖,但由于對(duì)于JS運(yùn)行環(huán)境中異步機(jī)制的不了解,所以遇到了一個(gè)棘手的問(wèn)題,始終無(wú)法解決,之后在與同事交流之后才恍然大悟。問(wèn)題的根節(jié)在于經(jīng)典的J...
閱讀 3834·2021-09-06 15:00
閱讀 2171·2019-08-30 15:53
閱讀 3277·2019-08-23 16:44
閱讀 944·2019-08-23 15:19
閱讀 1391·2019-08-23 12:27
閱讀 4187·2019-08-23 11:30
閱讀 581·2019-08-23 10:33
閱讀 369·2019-08-22 16:05