面試題 - 5 道 Promise 筆試題

面試題 - 5 道 Promise 筆試題


Promise 面試題主要體現在與定時器(setTimeout,setInterval),異步函數 async 等同時存在時其執行順序。

在做題之前抓住以下要點:

  1. JS 的循環執行機制是先執行宏任務,再執行微任務。然後執行第二個宏任務,微任務。第三個宏任務,微任務,,,以此循環。
  2. 如果宏任務中有微任務,則先執行宏任務,再執行宏任務中的微任務,最後執行第二個宏任務。
  3. 如果宏任務中有宏任務,則先執行宏任務,再執行第二個宏任務,最後執行宏任務中的宏任務。
  4. 如果微任務中有宏任務,則先執行微任務,再執行第二個宏任務,最後執行微任務中的宏任務。
  5. 如果微任務中有微任務,則先執行微任務,再執行微任務中的微任務,再執行第二個宏任務,最後執行微任務中的宏任務。
  6. 宏任務有:script、setTimeout\setInterval 定時器等。
  7. 微任務有:Promise 中的 then 方法、async 函數等。

注:以上定時器的宏任務是基於執行時間相同的情況下。如果時間不同,時間最長的始終最後執行。

詳情可以參考文章 JavaScript 事件循環機制(Event Loop)簡述

題目1:

先執行宏任務,再執行微任務。接着執行第二個宏任務…

<script>
    setTimeout(()=> {
        console.log("1")
    })
    var pro = new Promise((resolved,rejected)=>{
        console.log("2")
        resolved("3")
    });
    console.log("4")
    pro.then((res)=>{
        console.log(res)
    })
</script>

解析:
以上題目中 script 是一個宏任務,稱爲宏1。setTimeout 是第二個宏任務,稱爲宏2。pro.then 是一個微任務,稱爲 微1

先執行宏1。在 宏1 中。先執行 Promise 中的立即執行函數,執行代碼 console.log("2"),打印 2。接着執行同步任務console.log("4"),打印 4。宏1 執行完畢。

接着執行 微1,執行代碼 console.log(res) ,打印 3 。

接着執行 宏2,執行代碼 console.log("1") ,打印 1 。

結果:2 4 3 1

題目2:

如果宏任務中有微任務…

<script>
    var pro = new Promise((resolved,rejected)=>{
        setTimeout(()=> {
           console.log("2")
           resolved("3")
        })
    });
    console.log("4")
    pro.then((res)=>{
        console.log(res)
    })
    setTimeout(()=> {
        console.log("1");
    })
</script>

解析:
以上題目中 script 是一個宏任務,稱爲 宏1。立即執行函數 Promise 中 的 setTimeout 是第二個宏任務,稱爲宏2。在 宏2 中有 resolved 微任務,記爲 微1。最後一個 setTimeout 記爲 宏3

先執行 宏1。在 宏1 中。執行同步代碼 console.log("4") 打印 4。

接着執行 宏2,執行代碼 console.log("2") 打印 2。

接着執行 微1 ,執行代碼 console.log(res) 打印 3。

最後執行 宏3,執行代碼 console.log("1") 打印 1。

結果:4 2 3 1

題目3:

如果宏任務中有宏任務…

<script>
    setTimeout(()=> {
        console.log("1");
        setTimeout(()=> {
           console.log("5")          
        })
    })
    var pro = new Promise((resolved,rejected)=>{
        setTimeout(()=> {
           console.log("2")
           resolved("3")
        })
    });
    console.log("4")
    pro.then((res)=>{
        console.log(res)
    })
</script>

解析:
script 記 宏1,打印 4 就不再贅述了。第一個 setTimeout 記爲 宏2,裏面的 setTimeout 暫時放着。接下來在 Promise 中有一個 setTimeout 記爲 宏3。內部的 resolved 微任務記爲 微1。接着在第一個 setTimeout 中的 setTimeout 記爲 宏4
執行 宏2,執行代碼 console.log("1") 打印 1。
執行 宏3,執行代碼 console.log("2") 打印 2。
執行 宏3 中的 微1,執行代碼 console.log("3") 打印 3。
執行 宏4,執行代碼 console.log("5") 打印 5。

結果:4 1 2 3 5

題目4:

如果微任務中有宏任務…

<script>
    setTimeout(()=> {
        console.log("1")
    })
    var pro = new Promise((resolved,rejected)=>{
        setTimeout(()=> {
           console.log("2");
           resolved("3")
        })
    });
    pro.then((res)=>{
        console.log(res);
        setTimeout(()=> {
           console.log("4")
        })
    })   
     setTimeout(()=> {
        console.log("5")
    })
</script>

解析:
第一個 setTimeout 記爲 宏2,接下來在 Promise 中有一個 setTimeout 記爲 宏3。內部的 resolved 微任務記爲 微1。在 微1 內部又有一個 setTimeout 記爲 宏4。最後一個 setTimeout 記爲 宏5
執行 宏2,執行代碼 console.log("1") 打印 1。
執行 宏3,執行代碼 console.log("2") 打印 2。
執行 宏3 中的 微1,執行代碼 console.log("3") 打印 3。
執行 宏5,執行代碼 console.log("5") 打印 5。
執行 宏4,執行代碼 console.log("4") 打印 4。

結果:1 2 3 5 4

題目5:

如果微任務中有微任務…

<script>
    setTimeout(()=> {
        console.log("1")
    })
    var pro = new Promise((resolved,rejected)=>{
        resolved("3")
    });
    pro.then((res)=>{
        Promise.resolve().then(()=>{
            console.log("4")
        });
         setTimeout(()=> {
           console.log("2")
        })
        console.log(res)
    })
</script>

解析:
第一個 setTimeout 記爲 宏2,接下來在 Promise 中 resolved 記爲 微1微1 中的微任務記爲 微2微1 中的宏任務記爲 宏3
執行 微1,執行代碼 console.log(res) 打印 3。
執行 微2,執行代碼 console.log("4") 打印 4。
執行 宏2,執行代碼 console.log("1") 打印 1。
執行 宏3,執行代碼 console.log("2") 打印 2。

結果:3 4 1 2。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章