JS中同步和異步


首先,我們要知道,JavaScript的本質是一門瀏覽器腳本語言,在執行的時候是一行一行的執行,只有前面的代碼執行完了才會執行后面的代碼。JS是單線程語言指的就是這個意思。

同步和異步其實在進行任務執行順序時候都只有一條流水線,區別在於執行任務的順序不同

對於同步任務和異步任務,打個比喻:

有一堆學生在食堂排隊打飯,然后進門的時候有些學生領了個異步的牌子,有些學生沒有領,然后在窗口前排隊打飯的時候,食堂大叔規定,有異步牌子的學生出來重新組成一個小隊列,在窗口旁邊等待,沒有牌子的學生仍然在窗口前的主隊里排隊打飯。等主隊里沒有牌子的學生排隊打完飯之后,食堂大叔示意小隊列里有異步牌子的學生一個個的過來打飯。

拋開這個場景不談,在js中,同步和異步的概念,有很多博主的解釋就是“同步就是任務一個接一個的執行,前面的沒有執行完成后面的就一直等待”,“異步就是覺得一個任務要執行會花很長時間,所以先放着,去執行其他的任務,等輪到這個任務的時候再執行。”

很多小伙伴看到這里就懵逼了,怎么着,系統還能識別哪個任務執行時間長哪個短?有這么智能好用的系統?要是系統自動識別執行時長,任務管理不會亂套?所以,我個人覺得這些博主的描述是有很大問題的。

一個任務是否是異步的是看程序員在編寫代碼的時候是否將這個任務設置為異步,而不是說時間長的任務就一定是異步的,只是通常來講為了流暢性,編程者會將執行時間長的任務主觀的設置為異步。

所以說只要編程者不人為的對任務的執行順序進行干涉,那么任務就是同步的,會一條一條的執行。但是只要編程者人為的對某些任務的執行順序進行干涉,就是進行異步操作。

那么這里就涉及到一個問題了,怎么將一個任務設置為異步?

JS中最基礎的有兩種方式——setTimeout函數和setInterval函數。

如下代碼:

 1 <script type="text/javascript">
 2     console.log('1');
 3     setTimeout(function(){
 4         console.log('2');
 5     },0)
 6     setTimeout(function(){
 7         console.log('3');
 8     },0)
 9     setTimeout(function(){
10         console.log('4');
11     },0)
12     console.log('5');
13 </script>
View Code

上述代碼輸出順序為:1  5  2  3  4

其中因為2 3 4的輸出語句使用了setTimeout函數將其設定了等待時間(雖然設置的等待時間為0),所以它們3個被抽出來放在了另外的隊列里,只有沒被特別設置的任務按順序執行完之后才會開始執行這個特殊隊列的任務。所以會先把正常的1 5打印,然后才會開始打印2 3 4

這里我們會發現,1和5是按一般順序打印,因為JS是逐行執行的。但是同為異步任務的2 3 4的打印任務也是按照2 3 4的順序打印,是受加入隊列的順序影響。那么是不是說異步任務組成的隊列里執行順序和加入異步隊列的順序有關呢?並不是。只有異步任務的等待時間相同的時候,異步任務的執行順序才會收到計入隊列的順序影響。否則的話主要還是與每個任務設置的等待時間有關系。

例如下面這種情況:

 1 <script type="text/javascript">
 2     console.log('1');
 3     setTimeout(function(){
 4         console.log('2')
 5     },300)
 6     setTimeout(function(){
 7         console.log('2')
 8     },200)
 9     setTimeout(function(){
10         console.log('2')
11     },100)
12     console.log('5');
13 </script>
與等待時間有關

上述代碼的輸出順序為1  5  4  3  2

因為異步任務設置的等待時間不同,在同步任務執行完后,等待時間較短的任務優先執行,等待時間長的后執行。

把這些都搞清楚之后我們又難免會思考,這樣的異步操作都是對於只需要執行一次的任務進行排序,假如是要對多個需要按一定順序循環執行的異步任務呢?這個時候就需要用到promise隊列的鏈式調用,並且使用一個全局變量,在每完成一次循環后重置全局變量的值,並且在循環執行前檢查該全局變量的值。

詳細思路和是西安方法可以參考以下這篇博文。

關於JS下大批量異步任務按順序執行解決方案


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM