為什麼需要異步?why?來看一段代碼。
問題1:
for(var i=0;i<100000;i++){ } alert('hello world!!!');
這段代碼的意思是執行100...次後再執行alert,這樣帶來的問題是,嚴重堵塞了後面代碼的執行,至於為什麼,主要是因為JS是單線程的。
問題2:
我們通常要解決這樣一個問題,如果我們需要在head裡面加入script代碼的話,一般會將代碼寫在window.onload
裡面(如果操作了dom的話),你有沒有想過,為什麼要加window.onload
?原因就是你在操作dom的時候script後面的html代碼浏覽器還沒有開始加載,結果人家還沒有出生你就想著去娶她,這可能嗎?當然不可能,加上window。onload
之所以可以是因為,window.onload
裡面的代碼是在文檔全部加載完畢後執行的,也就相當於異步。
問題3:
有時候頁面並不需要一次性把所有的代碼都加載,更多的時候我們是按照某個需求才去加載某段代碼的。
什麼是單線程?
你可以這樣理解單線程就是代碼一段一段的執行,先執行前面的,前面的執行完了再執行後面的。
那JS中有哪些是異步的呢?
我相信這個東西,幾乎都用爛了,它就是setTimeout/setInterval當然還有Ajax,Ajax異步我相信大家都知道,當然也可以同步但沒人那麼去做,但是對於setTimeout和setInterval是異步可能有些小伙伴不同了解,下面說說為什麼說setTimeout是異步的。
setTimeout(function(){ console.log(0); },0) console.log(1); // 1 // 0
運行這段代碼後先打印的是1,而不是0,有些小伙伴是不是開始迷惑了,這裡我們雖然給setTimeout設置的是0秒後執行console.log(0)
,但是這個setTimeout很特別,因為它是異步的,我們先拋開這裡為什麼打印的是1然後才是0,先來聊聊什麼是異步。
什麼是異步?
比方說有些飯店你去吃飯需要提前預定,等其他人吃完你才能去,因此在其他人吃飯的時候你可以去干其他的事情,等其他人吃完了會有人來通知你,於是你可以去了,那麼對於代碼來說,如ajax,你定義了一個回調方法,這個回調方法並不會當時就去執行,而是等待服務器響應完成之後才會去執行這段代碼。
我們回到前面那段setTimeout身上,它的工作原理是這樣的,當你定義setTimeout那一刻起(不管時間是不是0),js並不會直接去執行這段代碼,而是把它扔到一個事件隊列裡面,當頁面中所有同步任務都干完了以後,才會去執行事件隊列裡面的代碼。什麼是同步,除了異步代碼就是同步—_—。
JS怎麼實現異步?
1.利用setTimout實現異步
setTimeout(function(){ console.log(document.getElementByTagName('body')[0]); },0)
但是setTimeout有些小小的問題,就是時間不精確,如果你想更快的執行這段代碼我們可以使用html5提供的一個函數。
requestAnimationFrame(function(){ console.log(document.getElementByTagName('body')[0]); })
requestAnimationFrame和setTimeout的區別就在於requestAnimationFrame比setTimeout更快執行,因此很多人用requestAnimationFrame來制作動畫。
2.動態創建script標簽
var head = document.getElementByTagName('head')[0]; var script = document.createElement('script'); script.src = '追夢子.js'; head.appendChild('script');
3.利用script提供的defer/async
<script src="xx.js" defer></script>
defer:當頁面加載完畢以後才去執行這段代碼。
<script src="xx.js" async></script>
async:異步執行script代碼
不過異步也是缺點的,比如下面這段代碼:
正常代碼:
try{ throw new Error('hello world'); }catch(err){ console.log(err); } // Error: hello world(…)
異步代碼:
try{ setTimout(function(){ throw new Error('hello world'); },0) }catch(err){ console.log(err); } // ReferenceError: setTimout is not defined(…)
可以發現catch裡面的代碼並沒有執行,也就是說try無法捕獲異步裡面的代碼。
總結
關於JS中的異步以及如何異步到這就基本結束,關於JS的異步算是老生常談了,但是還是希望本文的內容對大家能有一些幫助。