<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之旅 廣告
                [TOC] ![](https://box.kancloud.cn/d8a28e1b0015a0ab3a29de7b9ca72e13_1346x746.png) # [setTimeout(fn, 0) 和 setTimeout(fn, 1) 之間的區別? > https://stackoverflow.com/questions/8341803/what-is-the-difference-between-settimeoutfn-0-and-settimeoutfn-1 For Node.js,`0`is converted to`1`, so they are exactly the same:[https://github.com/nodejs/node/blob/master/lib/timers.js#L319](https://github.com/nodejs/node/blob/master/lib/timers.js#L319), and result might be: # 從promise、process.nextTick、setTimeout出發,談談Event Loop中的Job queue Event Loop 都不陌生,是指主線程從“任務隊列”中循環讀取任務,比如 例1: ```js setTimeout(function(){ console.log(1) },0); console.log(2) // 輸出 2 1 ``` 在上述的例子中,我們明白首先執行主線程中的同步任務,當主線程任務執行完畢后,再從event loop中讀取任務,因此先輸出 2,再輸出 1。 Event Loop 讀取任務的先后順序,取決于任務隊列(Job queue)中對于不同任務讀取規則的限定。比如下面一個例子: 例2: ```js setTimeout(function () { console.log(1); }, 0); Promise.resolve().then(function () { console.log(2); }); new Promise(resolve=>{ console.log(3) resolve() }).then(()=>{ console.log(4) }) console.log(5); // 輸出為 3 5 2 4 1 ``` 先輸出1,沒有問題,因為是同步任務在主線程中優先執行,這里的問題是`setTimeout`和`Promise.then`任務的執行優先級是如何定義的。 # 任務隊列(Job queue)中的執行順序 在 Job queue 中的隊列分為兩種類型:**macro-task** 和 **micro-task**。我們舉例來看執行順序的規定,我們設 macro-task 隊列包含任務: **a1, a2 , a3** micro-task 隊列包含任務: **b1, b2 , b3** ## 執行順序 1. 先執行 marco-task 隊列開頭的任務,也就是 **a1** 任務,執行完畢后; 2. 執行 micro-task 隊列里的所有任務,也就是依次執行**b1, b2 , b3**,執行完后**清空 micro-task 中已存在的所有任務**; 3. 接著執行 marco-task 中的第二個任務,依次循環。 了解完了 `macro-task` 和`micro-task` 兩種隊列的執行順序之后,我們接著來看,真實場景下這兩種類型的隊列里真正包含的任務(我們以 node V8 引擎為例),在node V8中,這兩種類型的真實任務順序如下所示: > 可以參考:node.js系列中的 Event Loop **macro-task** 隊列真實包含任務: * script 標簽(主程序代碼) * setTimeout * setInterval * setImmediate(Node.js 環境) * I/O * UI rendering\交互事件 * postMessage * MessageChannel **micro-task** 隊列真實包含任務(**一種盡快執行異步函數的方法,而不是放在調用堆棧的末尾**): * `process.nextTick` * `Promises` * `Object.observe` * `MutationObserver` 由此我們得到的執行順序應該為: **script(主程序代碼) —> process.nextTick —> Promises… ——> setTimeout ——> setInterval ——>setImmediate——> I/O ——> UI rendering** 在ES6中 macro-task 隊列又稱為 `ScriptJobs`,而 micro-task 又稱 `PromiseJobs` # 真實環境中執行順序的舉例 (0) ``` const bar = () => console.log('bar') const baz = ()=> console.log('baz') const foo = () => { console.log('foo') setTimeout(bar, 0) new Promise((resolve, reject) => resolve('should be right after baz, before bar') ).then(resolve => console.log(resolve)) baz() } foo() //====== foo baz should be right after baz, before bar bar ``` 在當前函數結束之前 resolve 狀態的 Promises 將在當前函數之后立即執行。 (1) `setTimeout`和`promise` 例3: ~~~ setTimeout(function () { console.log(3); }, 0); Promise.resolve().then(function () { console.log(2); }); console.log(1); ~~~ 我們先以第1小節的例子為例,這里遵循的順序為: **script(主程序代碼)——>promise——>setTimeout** 對應的輸出依次為:1 ——>2————>3 (2) `process.nextTick`和`promise`、`setTimeout` 例子4: ~~~ setTimeout(function(){console.log(1)},0); new Promise(function(resolve,reject){ console.log(2); resolve(); }).then(function(){console.log(3) }).then(function(){console.log(4)}); process.nextTick(function(){console.log(5)}); console.log(6); //輸出2,6,5,3,4,1 ~~~ 這個例子就比較復雜了,這里要注意的一點在定義 promise 的時候,promise 構造部分是同步執行的,這樣問題就迎刃而解了。 首先分析Job queue 的執行順序: **script(主程序代碼)——>process.nextTick——>promise——>setTimeout** I)**主體部分**: 定義promise的構造部分是同步的, 因此先輸出2 ,主體部分再輸出6(同步情況下,就是嚴格按照定義的先后順序) II)**process.nextTick**: 輸出5 III)**promise**: 這里的 promise 部分,**嚴格的說其實是 `promise.then` 部分**,輸出的是3,4 IV) **setTimeout** : 最后輸出1 綜合的執行順序就是: 2——>6——>5——>3——>4——>1 3)更復雜的例子 ```js setTimeout(function(){ console.log(1) },0); new Promise(function(resolve,reject){ console.log(2); setTimeout(function(){resolve()},0) }).then(function(){ console.log(3) }).then(function(){ console.log(4) }); process.nextTick(function(){ console.log(5) }); console.log(6); //輸出的是 2 6 5 1 3 4 ``` 這種情況跟我們(2)中的例子,區別在于`promise`的構造中,沒有同步的`resolve`,因此`promise.then`在當前的執行隊列中是不會觸發的,只有`promise`從`pending`轉移到`resolve`,才觸發`then`方法,而這個`resolve`是在一個`setTimout`時間中完成的,因此**3,4**最后輸出。 # 參考 [The JavaScript Event Loop: Explained](https://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/) [事件循環機制 Event-Loop及其延伸](https://github.com/amandakelake/blog/issues/26) [JavaScript 執行機制](https://www.manster.me/?p=711) [macrotask與microtask](http://www.ayqy.net/blog/javascript-macrotask-vs-microtask/) [從promise、process.nextTick、setTimeout出發,談談Event Loop中的Job queue](https://blog.csdn.net/liwusen/article/details/79509288) [Promise的隊列與setTimeout的隊列有何關聯?](https://www.zhihu.com/question/36972010)
                  <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>

                              哎呀哎呀视频在线观看