javascript的同步異步操作

首先,我們知道js是單線程的,一段代碼是從上往下,一句句執行的,前面的代碼往往先於後面的代碼執行。

一、同步操作,異步操作

同步操作、異步操作
首先得知道什麼是同步操作!就好比兩個人去食堂排隊打飯,排在前面的人打完之後才輪到後面的人打飯!這就是同步操作,大家按先來後到的順序做事!同步的好處就是簡單有規則,所以調試起來相對輕鬆,因爲大家都是按“規則”辦事的,不會出現“插隊”的情況,所以要“調查誰”,只要找到“它前面的相關人”,就能“逮住他”。同樣,同步也是有不好的地方的,比如資源不能充分利用,因爲“排隊”的時候不能做其他事情!只能等待,不能合理安排自己的任務等!
簡單來說,瀏覽器javascript同步任務指的是在執行棧排隊執行的任務,這個執行棧也就是所謂的javascript執行代碼的主線程!

異步操作【io(ajax獲取服務器數據)、用戶/瀏覽器自執行事件(onclick、onload、onkeyup等等)以及定時器(setTimeout、setInterval)這些異步操作】,同樣以去食堂打飯來說明!有一羣人去食堂打飯,小明發現在他前面有好多好多人在排隊,可是剛好他現在有一件急需要做的事情去處理,還好,他有一個很好的朋友在食堂吃飯,於是他跑過去跟他朋友說道:“哥們,我現在有很重要的事需要做,你能不能在人少的時候給我打電話告訴我一下,我再過來打飯!”於是,小明就去做他自己的事情去了,等沒有人排隊的時候,他的朋友打電話告訴他,可以過來打飯了!於是小明就很舒服地去打飯了。其實可以把這個過程就叫做異步,我們可以看到,異步很亮眼的一個好處就是,小明可以打飯和做其他事情兩不誤,所以能合理利用資源!當然了,這是需要付出代價的,至少在代碼實現上肯定比同步難!異步的不好的地方也有很多,很難調試和斷言,比如下面的代碼:

var a = '';
getData();//前面裏面包含一個異步操作,實現對a = 15的賦值操作
console.log(a);//我們發現在這個地方打印a是個空字符串,因爲在這個地方,異步操作並沒有執行
//解決方法就是使用回調,callback,如
getData(function(){
	console.log(a);//print  15
});

**一句話說明,瀏覽器中javascript異步任務是沒有進入執行棧的javascript任務,而是進入了一個稱爲事件隊列的地方去排隊等待執行,排隊的規則是先到的排在前面,後到的排在後面。**這些異步任務會在自己準備好之後,通過觸發一些事件來告知主線程,自己已經把該做的都做完 了,而且我還給你了一個函數你(主線程)去處理吧!這個函數也就是所謂的回調函數,到現在爲止,我才明白爲什麼回調函數爲什麼是異步的呢!(注:此回調函數不同於你在同步任務裏面寫的回調函數,反正記住一條,回調本身不是異步的,而是因爲回調是異步任務準備好之後給的函數是異步的!) 然後當主線程中的任務全部執行完成之後,也就是主線程空閒之後,會對事件隊列進行一個輪詢,從而執行了異步任務!

二、console.* 方法族

它們並不是javascript的正式部分,而是由宿主環境添加到javascript中的(參考《你不知道的javascript中卷》第二部分異步和性能 1.1 異步控制檯部分)。不同瀏覽器和javascript環境可以根據自己的意願來實現,有時候會引起混淆。
某些條件,某些瀏覽器並不會把console.log立即輸出。因爲,在許多程序中,不只是js啊,I/O是非常低速的阻塞部分,瀏覽器在後臺異步處理控制檯I/O 提高性能。

三、數組和console.log

數組是引用類型,console.log是異步操作,console.log在前面而對數組的操作是在後面時,console.log打印出來的數組可能是被操作之後的數組。如果遇到這種少見的情況,最好的選擇是在JavaScript 調試器中使用斷點,而不要依賴控制檯輸出。爲了避免這樣的情況發生,必須對數組進行深拷貝

參考:console.log機制
javascript線程及與線程有關的性能優化
JavaScript中十種一步拷貝數組的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章