日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景

發(fā)布時(shí)間:2023/12/10 javascript 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在今天之前我一直以為setTimeout這個(gè)函數(shù)是異步的,無(wú)意中看到了一篇關(guān)于setTimeout的文章。發(fā)現(xiàn)自己曾經(jīng)的認(rèn)識(shí)全是錯(cuò)誤的,趕緊總結(jié)下。


先看一段代碼:

var start = new Date(); setTimeout(function(){var end = new Date();console.log("Time elapsed: ", end - start, "ms"); }, 500);while (new Date - start <= 1000) {}

運(yùn)行這段腳本能夠看到:Time elapsed的值大概在1001ms左右,肯定會(huì)超過(guò)1000ms。也就是說(shuō):setTimeout失效了,指定的函數(shù)并沒(méi)有在500ms后運(yùn)行。而是延遲到1000ms后才運(yùn)行。


再看一段代碼:

function a() {setTimeout(function(){console.log(1);},0);console.log(2); } a();

執(zhí)行這段腳本能夠看到:先打印2后打印1,我們?cè)趕etTimeout里面指定了0ms,希望能馬上執(zhí)行,可是實(shí)際上沒(méi)有效果。


想要理解上面的2段代碼,我們得了解一下javascript中setTimeout的實(shí)現(xiàn)原理。首先牢記一點(diǎn):JavaScript 是單線程運(yùn)行的,也就是無(wú)法同一時(shí)候運(yùn)行多段代碼。

以下這段解釋來(lái)自這篇博客:

? ? ? ? JavaScript是單線程運(yùn)行的,無(wú)法同一時(shí)候運(yùn)行多段代碼。當(dāng)某一段代碼正在運(yùn)行的時(shí)候,全部興許的任務(wù)都必須等待,形成一個(gè)隊(duì)列。

一旦當(dāng)前任務(wù)運(yùn)行完畢,再?gòu)年?duì)列中取出下一個(gè)任務(wù),這也常被稱為 “堵塞式運(yùn)行”。所以一次鼠標(biāo)點(diǎn)擊,或是計(jì)時(shí)器到達(dá)時(shí)間點(diǎn),或是Ajax請(qǐng)求完畢觸發(fā)了回調(diào)函數(shù)。這些事件處理程序或回調(diào)函數(shù)都不會(huì)馬上運(yùn)行,而是馬上排隊(duì)。一旦線程有空暇就運(yùn)行。假如當(dāng)前 JavaScript線程正在運(yùn)行一段非常耗時(shí)的代碼,此時(shí)發(fā)生了一次鼠標(biāo)點(diǎn)擊。那么事件處理程序就被堵塞。用戶也無(wú)法馬上看到反饋。事件處理程序會(huì)被放入任務(wù)隊(duì)列。直到前面的代碼結(jié)束以后才會(huì)開(kāi)始運(yùn)行。假設(shè)代碼中設(shè)定了一個(gè) setTimeout,那么瀏覽器便會(huì)在合適的時(shí)間。將代碼插入任務(wù)隊(duì)列。假設(shè)這個(gè)時(shí)間設(shè)為 0,就代表馬上插入隊(duì)列,但不是馬上運(yùn)行。仍然要等待前面代碼運(yùn)行完成。

所以 setTimeout 并不能保證運(yùn)行的時(shí)間。是否及時(shí)運(yùn)行取決于 JavaScript 線程是擁擠還是空暇。


也就是說(shuō)setTimeout僅僅能保證在指定的時(shí)間過(guò)后將任務(wù)(須要運(yùn)行的函數(shù))插入隊(duì)列等候,并不保證這個(gè)任務(wù)在什么時(shí)候運(yùn)行。運(yùn)行javascript的線程會(huì)在空暇的時(shí)候,自行從隊(duì)列中取出任務(wù)然后運(yùn)行它。javascript通過(guò)這樣的隊(duì)列機(jī)制。給我們制造一個(gè)異步運(yùn)行的假象。

var start = new Date(); setTimeout(function(){var end = new Date();console.log("Time elapsed: ", end - start, "ms"); }, 500);console.log("task finished.");我們之所以會(huì)感覺(jué)到這段代碼是在異步運(yùn)行,這是由于javascript線程并沒(méi)有由于什么耗時(shí)操作而堵塞,所以能夠非常快地取出排隊(duì)隊(duì)列中的任務(wù)然后運(yùn)行它。

如今我們知道了setTimeout的原理了,如今看下setTimeout(0)的使用場(chǎng)景。以下這個(gè)樣例來(lái)自這篇文章。

<input type="text" οnkeydοwn="show(this.value)"> <div></div> <script type="text/javascript">function show(val) {document.getElementsByTagName('div')[0].innerHTML = val;} </script>這里綁定了 keydown 事件,意圖是當(dāng)用戶在文本框里輸入字符時(shí)。將輸入的內(nèi)容實(shí)時(shí)地在 <div> 中顯示出來(lái)。可是實(shí)際效果并不是如此,能夠發(fā)現(xiàn)。每按下一個(gè)字符時(shí),<div> 中僅僅能顯示出之前的內(nèi)容,無(wú)法得到當(dāng)前的字符。


<input type="text" οnkeydοwn="var self=this; setTimeout(function() {show(self.value)}, 0)"> <div></div> <script type="text/javascript">function show(val) {document.getElementsByTagName('div')[0].innerHTML = val;} </script>

這段代碼使用了setTimeout(0)就能夠?qū)崿F(xiàn)需要的效果了。

這里事實(shí)上涉及2個(gè)任務(wù),1個(gè)是將鍵盤輸入的字符回寫到輸入框中。一個(gè)是獲取文本框的值將其寫入div中。第一個(gè)是瀏覽器自身的默認(rèn)行為。一個(gè)是我們自己編寫的代碼。非常顯然。必需要先讓瀏覽器將字符回寫到文本框。然后我們才干獲取其內(nèi)容寫到div中。改變順序,這這正是setTimeout(0)的作用。


參考文章:setTimeout(0) 的作用


總結(jié)

以上是生活随笔為你收集整理的javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout(0)的使用场景的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。