[英]Determine promise state using Promise.race and setImmediate
TL;DR :已經解決的 promise 是否總是在比賽中擊敗setImmediate
?
背景:
有時您想知道 promise 是否已解析而不等待其完成。 有一些舊的遺留技巧,例如使用util.inspect
獲取內部 state 並檢查它是否包含字符串"<pending>"
。 然而,一個更穩定的解決方案是使用Promise.race()
來等待未知的 promise 並有一個(非常小的)超時。
const p = doSomething();
const result = await Promise.race([
p,
new Promise(resolve => setTimeout(resolve, 1))
]);
if (result) {
// p was resolved within 1 ms!
...
}
這將最多等待 1 毫秒以獲取result
,然后該結果將包含p
的解析值或undefined
的值。 如果需要,“超時承諾”當然可以返回不同於undefined
的東西,以區分從doSomething()
返回的實際undefined
值:
const PENDING = Symbol.for('PENDING');
const result = await Promise.race([
p,
new Promise(resolve => setTimeout(() => resolve(PENDING), 1))
]);
if (result !== PENDING) {
...
}
現在我們將從doSomething()
或唯一符號PENDING
獲取解析值。
現在回答我的問題。 除了setTimeout
之外,還有一個setImmediate
function,它基本上就像一個立即到期的計時器; 它只是在解析之前給事件循環一個 go。 在我上面的Promise.race
表達式中使用它時,根據經驗它似乎有效,即,如果p
已經解決,它將在比賽中擊敗setImmediate
,但我想知道是否有任何這樣的保證- 或者我是否應該使用一個 1 毫秒的定時器來保證一個已解決的 promise 打敗定時器?
我已經嘗試將p
放在傳遞給Promise.race
的數組中的setImmediate
promise 之前和之后,它可以雙向工作,但我仍然擔心它可能會隨機運行或取決於操作系統? 或者setImmediate
等待一輪 I/O 的事實是否足以保證任何已解決的承諾都將獲勝?
從文檔中:
在 I/O 事件回調之后安排回調的“立即”執行
編輯:
我發現即使這樣“似乎”也有效:
const result = await Promise.race([p, new Promise(resolve => resolve(PENDING))]);
或者實際上什至是這樣的:
const result = await Promise.race([p, Promise.resolve(PENDING)]);
但是,這里的順序很重要。 如果p
被解決並且在超時 promise 之前,它將獲勝,但如果它在數組中的超時 promise 之后它將失敗。 但問題是一樣的:如果已經解決,這種方法是否保證讓p
獲勝?
考慮 Nodejs 中的以下代碼
參考 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
setImmediate(() => console.log("setImmediate"));
setTimeout(() => console.log("setTimeout"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("Promise"));
console.log("sync");
Output:
您可以注意到順序,這就是它按順序執行的方式。
sync
nextTick
Promise
setTimeout
setImmediate
為了回答您的問題,我們可以將代碼包裝在 Promises 中,如下所示:
(async function main() {
const result = await Promise.race([
new Promise(resolve => resolve("sync")),
new Promise(resolve => setImmediate(() => resolve("setImmediate"))),
new Promise(resolve => setTimeout(() => resolve("setTimeout"))),
new Promise(resolve => Promise.resolve().then(() => resolve("Promise"))),
new Promise(resolve => process.nextTick(() => resolve("nextTick"))),
]);
console.log({ result });
})();
因為sync function是先執行的,所以會返回。
Output:
{ result: 'sync' }
可以評論上面Promise其中一個,看看哪個先解決。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.