今天去面試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的機制了解
大致上分為六個階段:
這六個階段根據官方概述:
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或是其他方式去更新用戶的頁面。
不必等到後端轉檔完畢 才一次把所有物品都丟到前端