<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                >[success] # js -- 如何通過事件循環運行異步 現在有一個新問題,這些容器提供的**異步api,如何跟'js 引擎'形成交互的**,這些執行后**異步api回調函數的內容存在哪里,這些回調函數又在什么實際推進'js 引擎'的棧中** 1. 需要容器提供的兩個東西'**事件循環和回調隊列**' 2. 下圖的模型圖還不完整,因為在'es6'的時代開始出現了'promise',需要有新的存儲位置,這個在后續章節會說明 * 現在得到一個模型圖 ![](https://img.kancloud.cn/32/c0/32c0844940c5b2d1aa98a5f03451bccf_700x386.png) >[danger] ##### 回調隊列 1. 回調隊列也稱為 **'消息隊列'或'任務隊列'** 2. 當代碼從上而下的推入'js 引擎'執行棧中的時候,如果該函數**包含Web API調用**,這部分函數**將交給容器對應的webApi線程去執行**,當完成這部分內容規定執行條件時候,例如**定時器所定的時長,xhr請求完成**將這部分**webAPI中的回調函數交給消息隊列** **簡單**的說在Web API模塊中,**異步操作在相應的線程中處理完成得到結果之后,會把結果注入異步回調函數的參數中,并且把回調函數推入回調隊列中** * **做一個比喻**當你的 **JavaScript 程序發出了一個 Ajax 請求去服務器獲取數據**,你在一個函數(回調)中寫了 '**response**' 代碼,然后 JS 引擎就會告訴宿主環境**如果你完成了這個網絡請求,并且獲取到數據的時候,請回來調用這個函數**,瀏覽器就開始監聽什么時候完成,當發現完成了,它將會把回調函數插入到事件循環隊列里然后執行。 >[danger] ##### 事件循環 **現在新的問題就是,這些在消息隊列中的回調函數什么時候在回到'js引擎'的中?** 1. 這時候就需要每個容器都提供的'**事件循環**',**事件循環的唯一任務是查看回調隊列, 一旦回調隊列中有東西掛起,并且當'js引擎'棧為空,事件循環一次將一個回調函數推送到棧。** 稍后,'js引擎'棧將執行回調函數 * 注 '**事件循環**'去監控調用棧和回調隊列。如果調用棧是空的,它就會取出隊列中的第一個事件,然后將它壓入到調用棧中,然后運行它 >[danger] ##### 兩段代碼來看整體效果 [如果你想有更好的體驗請看這里](http://latentflip.com/loupe/) ~~~ console.log('Hi'); setTimeout(function cb1() { console.log('cb1'); }, 5000); console.log('Bye'); ~~~ * 如圖 ![](https://img.kancloud.cn/5c/5b/5c5b41e37c793ce1fad4f342257bbede_800x600.gif) ~~~ function printHello() { console.log('Hello from baz'); } function baz() { setTimeout(printHello, 3000); } function bar() { baz(); } function foo() { bar(); } foo(); ~~~ * 如圖 ![](https://img.kancloud.cn/35/36/3536a28cf44f7aff3d9abaf26cd95539_967x579.gif) * 根據上面圖總結**setTimeout(…) 是如何工作的**,`setTimeout(…)`**不會自動的把你的回調放到事件循環隊列中**。它設置了一個定時器。**當定時器執行完畢,宿主環境會將你的回調放到事件循環隊列中,以便在以后的循環中取走執行它。** ~~~ setTimeout(myCallback, 1000); ~~~ 這并不意味著`myCallback`將會在 1,000ms 之后執行,而是,在 1,000ms 之后將被添加到事件隊列。然而,這個隊列中可能會擁有一些早一點添加進來的事件 —— 你的回調將會等待被執行 >[info] ## 總結 1. 首先依舊明確 **'js 引擎是單線程而且也沒有異步',異步是引擎所在容器提供**,所在**容器會在運行時,提供一些掛載在全局的額外暴露出來的容器api,這些api中他們會被容器中的其他線程代理**,**當引擎執行時候遇到這些容器提供的api**,**js 引擎就會將這些api返回給其對應的線程去執行,當這些線程執行完畢這些內容后,會將這些api里的回調函數,放到'消息隊列中','事件循環'去監控調用棧和回調隊列。如果調用棧是空的,它就會取出隊列中的第一個事件,然后將它壓入到調用棧中** 2. **注意的一點'事件循環一次將一個回調函數推送到棧'** 3. 永遠只有JS引擎線程在執行JS腳本程序,其他線程只負責將滿足觸發條件的處理函數推進事件隊列,等待JS引擎線程執行。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看