在我正在從事的專案中,我們有時會因為糟糕的承諾從未解決而等待一些從未解決的問題。
這真的很難找到哪個 await 導致代碼停止運行并找到 node.js 卡住的位置。
這是問題的代碼說明。假設“getRandomlyStuckedPromise”是來自外部庫的承諾:
getRandomlyStuckedPromise = () => new Promise((resolve) => {
if (Math.random() > 0.9) return;
resolve(); // never get called some times
});
await getBadPromise();
await getBadPromise();
await getBadPromise();
await getBadPromise();
await getBadPromise();
await getBadPromise(); // Node.js stuck at one line ... how to know which one ?
await getBadPromise();
await getBadPromise();
如果您已經遇到過這種問題,您是否知道 node.js 中的一些工具或任何技術來查找哪個 await node.js 卡住了?
uj5u.com熱心網友回復:
您需要以一種或另一種方式包裝或記錄承諾。幸運的是,您可以撰寫一個非常緊湊的包裝器。如果您同時等待多個承諾,您可以將它們排列為一個陣列,然后使用map包裝每個承諾以傳遞到Promise.all您需要它們的地方或任何地方。
(async () => {
const getBadPromise = () => new Promise((resolve, reject) => {
if (Math.random() > 0.8) return;
if (Math.random() > 0.8) reject(new Error("Promise failed on its own"));
resolve();
});
/**
* Logs the given promise with the given label.
*
* Will reject the promise after a timeout if it does not return.
*/
function wrap(label, promise) {
const timeout = 1000;
// Log promise creation.
console.log(`Start (${label})`);
return new Promise((resolve, reject) => {
// Set up timeout handler to reject.
const timeoutHandler = setTimeout(() => {
reject(new Error(`Timeout (${label}, ${timeout})`));
}, timeout);
// Promisify value (in case it's a primitive). Once it resolves,
// log it, clear the timeout, and pass the results out of the function.
Promise.resolve(promise).finally(() => {
console.log(`End (${label})`);
clearTimeout(timeoutHandler);
}).then(resolve, reject);
});
}
console.log("Start.");
await wrap("1", getBadPromise());
await wrap("2", getBadPromise());
await wrap("3", getBadPromise());
await wrap("4", getBadPromise());
await wrap("5", getBadPromise());
await wrap("6", getBadPromise());
await wrap("7", getBadPromise());
await wrap("8", getBadPromise());
await wrap("9", getBadPromise());
console.log("Done.");
})().catch(console.error);
uj5u.com熱心網友回復:
基于@JeffBowman 的提議,我做了一個稍微不同的包裝器 =>
const withRejectTimeout = (promise, timeout = 120000 /* 2mn */) => {
const timeoutError = new Error('Promise timeout');
return Promise.race([
promise,
new Promise((_, reject) => setTimeout(() => reject(timeoutError), timeout)),
]);
};
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
await withRejectTimeout(getBadPromise());
這使用錯誤堆疊跟蹤來幫助定位導致問題的等待。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/358587.html
