簡體   English   中英

使用 Promise.race 和 setImmediate 確定 promise state

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM