1. 程式人生 > >Event Loop(JS的執行機制)

Event Loop(JS的執行機制)

JS引擎的執行機制:(單執行緒和event Loop的執行機制)
    參考:
        https://segmentfault.com/a/1190000012806637
        http://www.ruanyifeng.com/blog/2013/10/event_loop.html
    注意:
        Worker API可以實現多執行緒,但是JavaScript本身始終是單執行緒的
    1.什麼是even Loop的執行機制
        簡單的來說,就是在程式中,設定兩個執行緒:
            一個執行緒,負責程式本身的執行,稱為主執行緒
            一個執行緒負責主執行緒與其他執行緒的操作(主要是各種IO操作),稱為event Loop執行緒(也叫訊息執行緒)
        執行原理:
            1.主程式遇到I/O的時候,交給event Loop執行(自己則繼續往後面執行)
            2.等到Event LOop執行緒執行完畢之後,返回給主執行緒
            3.主執行緒觸發,相應的回撥操作
            4.執行完畢
        結論:
            這樣,就解決了單執行緒的問題
            這種執行方式,叫做非同步模式或非阻塞模式(node JS 也是這樣的)
    2.JS是單執行緒的歷史原因
        為了簡單
        佇列,併發,程序和執行緒--在瀏覽器中(怎麼簡單,怎麼來)
    3.為啥要使用非同步:
        設計到了JS的執行順序
            自上而下的  (有一段程式碼太大,後面就會卡死)
            這個就叫做阻塞,於是就有了非同步的解決方案.
    4.非同步的執行案例:
        程式碼:
            <script>
                console.log('開始的console');
                setTimeout(function () {
                    console.log('定時器')
                },0);
                console.log('結尾的console');
            </script>
        對於上面案例的分析:
            開始的console-->結尾的console--->定時器
        再看一眼執行的順序:
            1.判斷程式碼是同步的還是非同步的
                同步的,就進入主執行緒
                非同步的,就進入event tablt
            2.非同步的任務在event table 裡面註冊函式,當滿足觸發條件的時候進入event queque(就是事件佇列)
            3.當主執行緒空閒的時候,就去event  queque裡面檢視是否有可執行的非同步任務
                如果,有 就推入到主執行緒裡面
        於是,上面的就可以解釋了
            setTimeout()  是一個非同步的任務(空閒的時間才會執行他)
===================================================================
另一個案例:
    程式碼:
        <script>
            setTimeout(function () {
                console.log('定時器開始了');
            })


            new Promise(function (resolve) {
                console.log('執行for迴圈之前');
                for(var i=0;i<1000;i++){
                    i==99&&resolve();
                }
            }).then(function () {
                console.log('執行了then函數了')
            })


            console.log('程式碼執行結束了');
        </script>
    在此之前,我們需要了解一下ES6的一些語法
        ES6(碰到一個,學一個)
        參考:
            http://es6.ruanyifeng.com/#docs/promise
            https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
        關於promise(承諾)
            1.他是一個容器(物件方式的容器)
            2.容器裡面存放的是某個非同步操作(未來才會結束的事件)
            3.容器裡面的內容有什麼特點呢??
                1.物件的狀態不受外部的影響
                    那他有哪幾種會狀態呢??
                        pending(進行中)、fulfilled(已成功)和rejected(已失敗)
                    只有非同步操作的結果,可以改變狀態
                2.一旦狀態改變就不會再變,任何時候都是這個結果
                    什麼是狀態改變:
                        狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected
                    為了方便,我們把
                        resolved(已定型)統一隻指fulfilled
            4.promise的語法結構:
                Promise()建構函式,建立promise物件
                程式碼:
                    new Promise(function(resolve, reject){  //必須寫上回調函式,否則會報錯的
                        //引數,resolve和reject ,由 JavaScript 引擎提供,不用自己部署。
                    }).then(function(value){
                        //成功的返回值
                        靜態方法 Promise.resolve返回一個promise物件,這個promise物件是被解析後(resolved)的
                    },function(error){
                        //失敗的返回值
                    })
                關於這兩個引數:(貌似都是返回一個物件啊)
                    1.Promise.resolve()方法
                        靜態方法 Promise.resolve返回一個promise物件,這個promise物件是被解析後(resolved)的
                        語法:
                            Promise.resolve(value);
                            Promise.resolve(promise);
                            Promise.resolve(thenable);
                    2.Promise.reject(reason)方法返回一個用reason拒絕的Promise\
    擴充套件結束,我們來分析這個案例:
        執行結果:
            執行for迴圈之前-->程式碼執行結束了--->執行了then函數了--->定時器開始了
        結構分析:
            1.由上到下執行
                setTimeout()  放在全域性的非同步執行佇列中(巨集任務)
            2.建立promise物件
                回撥函式立即執行,列印執行for迴圈之前
                then 是非同步的,存在當前的非同步執行佇列中(微任務)
            3.全域性
                程式碼執行結束了
            4.返回到那個內部的非同步 Event Loop裡面執行
                執行then函式
            5,執行全域性的非同步佇列中的函式
        執行完主程式之後
            先看看微任務有未執行的嗎,如果有,就先執行他-=--這不是開小灶嗎
            之後執行紅任務
        疑惑:
            就兩個執行緒
                這個多了一個,算是巢狀嗎????
還有一個坑:
   程式碼:
     setTimeout(
        function(){
            console.log('執行了')
         },3000 )  
    其實,不是3s之後執行
    而是,3s之後,被推入Event Loop執行佇列中
    主程式有空閒,就來執行該程式
    執行的條件
        所以只有滿足 (1)3秒後 (2)主執行緒空閒,同時滿足時,才會3秒後執行該函式