iT邦幫忙

1

NodeJS EventLoop 和 Promise 關係簡述

前言

今天去面試NodeJS的時候面試官問了關於Promise和Event Loop相關的問題
雖然平時操作經常用到但實際被問的時候還是解釋的不太清楚
其中最讓我印象深刻的問題是Promise用在哪裡

我的回答是Promise是非同步操作,為了避免耗時的操作堵塞Process
結果被糾正說Promise應該是同步,覺得很怪所以回家整理了一下這方面的資料
其實這個問題已經有很多詳解了,不過想說整理一遍,對自己的觀念也比較清晰
如果有錯歡迎指教


內文

Promise和Event Loop其他的文章應該有更詳細的說明,這裡不多做贅述。
直接上code:

var fs = require('fs');
function test(){
    console.log(1);
    let promise = new Promise((reslove,reject)=>{
        let data = fs.readFileSync(`${__dirname}/package.json`);
        reslove(6);
        console.log(2);
    });
    setTimeout(()=>{console.log("x")},0);
    console.log(3);
    promise.then((s)=>{
        console.log(s);
    });
    console.log(4);
    for(let i = 0; i<100;i++){
        let data = fs.readFileSync(`${__dirname}/package.json`);
    }
    
    return 5;
};
console.log(test());
function a(){
    return 0;
}
console.log(a());

輸出結果:

1
2
3
4
5
0
6
x

發生了什麼

我們可以先從Event Loop的機制了解
大致上分為六個階段:https://ithelp.ithome.com.tw/upload/images/20210105/20134017nVBP9YnzkA.png

這六個階段根據官方概述:

1.定时器:本阶段执行已经被 setTimeout() 和 setInterval() 的调度回调函数。

2.待定回调:执行延迟到下一个循环迭代的 I/O 回调。

3.idle, prepare:仅系统内部使用。

4.轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞。

5.检测:setImmediate() 回调函数在这里执行。

6.关闭的回调函数:一些关闭的回调函数,如:socket.on('close', ...)。

根據上面的說明可以很清楚的了解到,基本上callback的執行階段會落在第六步驟
因此當函式都Return完畢後才會輪到callback
所以在第四步驟輸出123450
第六步驟輸出6
而x是由於是setTimeout()的callback產生的行為
在使用的當下他會屬於次輪循環
因為使用當下已經處於第四步驟,而setTimeout的callback屬於第一步驟
於是等到次輪循環的時候才會將x顯示出來


結論

至於為什麼面試官會說Promise會是同步操作的原因,事後打電話回去了解。
才知道原來他指的是建構Promise當下= ="(汗
但基本上Promise都是用於非同步操作,在大多數的事件結束後才去執行這個事情

這樣的好處以網站來說,假設用戶進行了一個轉檔的操作並且要顯示在前端
可以先渲染前端頁面,而轉檔這件大事,則是在渲染完前端後,再去執行

執行完畢後,再透過AJAX或是其他方式去更新用戶的頁面。

不必等到後端轉檔完畢 才一次把所有物品都丟到前端


尚未有邦友留言

立即登入留言