1. 程式人生 > >深入理解JS中的--同步和非同步

深入理解JS中的--同步和非同步

  • JS中的兩種程式設計思想:同步、非同步
  • JS是單執行緒的 --> JS就是一個傻子,腦子一根筋,做著當前的這件事情,沒有完成之前,絕對不會做下一件事情
  • 同步就是 --> 上一件事情沒有完成,繼續處理上一件事情,只有上一件事情完成了,才會做下一件事情 --> JS中大部分都是同步程式設計

<script type="text/javascript">
             // JS中的兩種程式設計思想:同步、非同步
             //JS是單執行緒的 --> JS就是一個傻子,腦子一根筋,做著當前的這件事情,沒有完成之前,絕對不會做下一件事情
             // 同步就是 --> 上一件事情沒有完成,繼續處理上一件事情,只有上一件事情完成了,才會做下一件事情
             //                         --> JS中大部分都是同步程式設計
//             for (var i = 0;i < 10000;i++) {
//                 if (i === 9999) {
//                     console.log("迴圈結束了"); // --> (1)
//                 }
//             }
//             console.log("ok"); // --> (2)
             // --> for迴圈就是同步程式設計,只有迴圈結束後,才會繼續執行下面的程式碼            
             
//             while (1) {
//                 
//             }
//             console.log("ok"); // --> 永遠不會執行,因為上面的迴圈是死迴圈,迴圈永遠不會結束

  • 2、非同步 --> 規劃要做一件事情,但是不是當前立馬去執行這件事情,需要等一定的時間,這樣的話,我們不會等著他執行,而是繼續執行下面的操作
    • –> “只有當下面的事情都處理完成了,才會返回頭處理之前的事情;如果下面的事情並沒有處理完成,不管之前的事情有沒有到時見,都踏踏實實的給我等著”
    • –> 在JS中,非同步程式設計只有四種情況:
      • –> 定時器都是非同步程式設計的
      • –> 所有的事件繫結都是非同步程式設計的
      • –> Ajax讀取資料都是非同步程式設計的,我們一般設定為非同步程式設計
      • –> 回撥函式都是非同步程式設計的

            // 2、非同步 --> 規劃要做一件事情,但是不是當前立馬去執行這件事情,需要等一定的時間,這樣的話,我們不會等著他執行,而是繼續執行下面的操作
            //                      --> “只有當下面的事情都處理完成了,才會返回頭處理之前的事情;如果下面的事情並沒有處理完成,不管之前的事情有沒有到時見,都踏踏實實的給我等著”
            // --> 在JS中,非同步程式設計只有四種情況:
            //          --> 定時器都是非同步程式設計的
            //          --> 所有的事件繫結都是非同步程式設計的
            //          --> Ajax讀取資料都是非同步程式設計的,我們一般設定為非同步程式設計
            //          --> 回撥函式都是非同步程式設計的
            
            
//            var n = 0;
//            window.setTimeout(function () {
//                n++;
//                console.log(n);  // --> 1 (2)
//            },1000);
//            console.log(n);  // --> 0 (1)
//            // --> 先輸出48行,0 --> 再輸出46行,1
            
            
            //每一個瀏覽器對於定時器的等待時間都有一個最小的值,谷歌5-6毫秒;IE 10-13毫秒
            //如果設定的等待時間小於這個值,不起作用,還是需要等待最小時間才執行; --> 尤其是寫0也不是立即執行
//            var n = 0;
//            window.setTimeout(function () {
//                n++;
//                console.log(n);  // --> 1 (2)
//            },0); // --> 0不是立即執行
//            console.log(n);  // --> 0 (1)
            // --> 先輸出60行,0 --> 再輸出57行,1
            
            
            
                //--> 我們定時器設定的等待時間不一定就是最後的執行時間,如果定時期之後還有其他的事情正在處理中,不管定時器的時間有沒有到,都是不會執行定時器的
//            var n = 0;
//            window.setTimeout(function () {
//                n++;
//                console.log(n); // --> 不執行的
//            },0);
//            console.log(n); // --> 0 (1)
//            while (1) { // --> 死迴圈
//                n++;
//            }
//             console.lgo(n);  // --> 不執行的
             //只能執行1次,因為死迴圈這件事情一直執行完成不了
             
             
             // 任務佇列池
//             var n = 0;
//             window.setTimeout(function () {
//                 n += 2;
//                 console.log(n);  // --> 7 (4)
//             },20);
//              window.setTimeout(function () {
//                 n += 5;
//                 console.log(n);  // --> 5 (3)
//             },5);
//             console.log(n);  // --> 0 (1)
//             for (var i = 0;i < 1000000;i++) {
//                 
//             }
//             console.log(n);  // --> 0 (2)
             // 0 86、 0 90、 5 7 
             
             
             // 
             for (var i = 0;i < oLis.length;i++) {
                 oLis[i].onclick = function () {
                     tabChange(i);
                 };
             }
             
             
        </script>

任務佇列池

JavaScript為什麼是單執行緒?eventloop

  • JavaScript的單執行緒,與它的用途有關。作為瀏覽器指令碼語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單執行緒,否則會帶來很複雜的同步問題。

  • 非同步執行:

1)所有同步任務都在主執行緒上執行,形成一個執行棧(execution context stack)。

(2)主執行緒之外,還存在一個"任務佇列"(task queue)。只要非同步任務有了執行結果,就在"任務佇列"之中放置一個事件。

(3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務佇列",看看裡面有哪些事件。那些對應的非同步任務,於是結束等待狀態,進入執行棧,開始執行。

(4
)主執行緒不斷重複上面的第三步。 主執行緒從”任務佇列”中讀取事件,這個過程是迴圈不斷的,所以整個的這種執行機制又稱為Event Loop(事件迴圈)。