我喜歡并行運行一組函式,當所有函式都完成后,我喜歡運行一些最終的東西。我的 JavaScript 看起來像這樣:
const logger = console;
const functionOne = function () {
logger.info("Starting functionOne");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
}, 20000);
});
};
const functionTwo = function () {
logger.info("Starting functionTwo");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionTwo after 10 sec.");
}, 10000);
});
};
const runningFunctions = async function () {
logger.info('Start jobs');
functionOne();
functionTwo();
}
runningFunctions();
logger.info(`All done after 20 sec.`);
原則上我的日志輸出應該是這樣的:
2021-11-24 16:54:31.111 [info] -> Start jobs
2021-11-24 16:54:31.112 [info] -> Starting functionOne
2021-11-24 16:54:31.113 [info] -> Starting functionTwo
2021-11-24 16:54:41.115 [info] -> Finished functionTwo after 10 sec.
2021-11-24 16:54:51.115 [info] -> Finished functionOne after 20 sec.
2021-11-24 16:54:51.116 [info] -> All done after 20 sec.
我嘗試了不同的解決方案,例如
runningFunctions().then(
() => { logger.info(`All done after 20 sec.`) }
).catch(
err => { logger.error(err) }
);
或者
Promise.all([functionOne(), functionTwo()]).then(() => {
logger.info(`All done after 20 sec.`);
});
和許多其他人,但沒有一個按預期作業。在大多數情況下,訊息All done after 20 sec.在 functionOne/functionTwo 啟動后立即出現,或者根本不列印最終日志。
我該如何撰寫腳本?
uj5u.com熱心網友回復:
ES2020 中的新功能是Promise.allSettled.
該
Promise.allSettled()方法回傳一個承諾,該承諾在所有給定的承諾已完成或被拒絕后決議,并帶有一個物件陣列,每個物件描述每個承諾的結果。
Promise.all如果任何承諾被拒絕,這與立即拒絕略有不同。
function getData(count) {
return new Promise((res, rej) => {
setTimeout(() => {
if (count !== 2) res(count);
rej(count);
}, 1000);
});
}
async function main() {
const promises = [getData(1), getData(2), getData(3)];
const response = await Promise.allSettled(promises);
console.log(response);
}
main();
uj5u.com熱心網友回復:
首先,您必須修復兩者functionOne(),functionTwo()以便他們resolve()在計時器觸發時創建他們的承諾。沒有它,他們只是創建一個永遠不會解決的承諾,這不是很有用,并且在完成后不會通知呼叫者。
然后,要并行運行它們,使用Promise.all()which 將讓您呼叫兩個函式,然后它將一起跟蹤兩個回傳的承諾,并且從呼叫回傳的承諾Promise.all()將在兩個函式都完成或拒絕時解決,如果其中一個函式拒絕了它們承諾。
如果你在這里的例子,你的承諾都沒有拒絕,但是如果你想知道所有承諾什么時候完成,即使有一些拒絕,那么你可以使用Promise.allSettled()代替Promise.all()。主要區別在于,Promise.all()一旦您通過它的任何承諾被拒絕,Promise.allSettled()它將短路并拒絕它的承諾,而將等到所有承諾完成,無論是否解決/拒絕。雖然您沒有在這里使用它,但它的已解決值Promise.allSettled()也不同,因此您可以分辨哪些承諾被拒絕,哪些已解決。
這是一個可運行的(在代碼段中)示例,它使用Promise.all(). Promise.allSettled()如果這是您希望看到的行為,您可以換入:
const logger = console;
const functionOne = function () {
logger.info("Starting functionOne");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
resolve();
}, 20000);
});
};
const functionTwo = function () {
logger.info("Starting functionTwo");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionTwo after 10 sec.");
resolve();
}, 10000);
});
};
const runningFunctions = function () {
logger.info('Start jobs');
return Promise.all([functionOne(), functionTwo()]);
}
runningFunctions().then(() => {
logger.info(`All done after 20 sec.`);
}).catch(err => {
console.log(err);
});
請注意,如果您運行該代碼段,您可以看到每個日志陳述句的實際時間,以驗證事情是否在適當的時間發生。
要按順序運行這兩個函式,您可以只await呼叫每個函式。這是一個可運行的(在代碼段中)示例:
const logger = console;
const functionOne = function () {
logger.info("Starting functionOne");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
resolve();
}, 20000);
});
};
const functionTwo = function () {
logger.info("Starting functionTwo");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionTwo after 10 sec.");
resolve();
}, 10000);
});
};
const runningFunctions = async function () {
logger.info('Start jobs');
await functionOne();
await functionTwo();
}
runningFunctions().then(() => {
logger.info(`All done after 30 sec.`);
}).catch(err => {
console.log(err);
});
uj5u.com熱心網友回復:
也許你需要Promise.all()?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Promise.all() 方法將一個可迭代的 Promise 作為輸入,并回傳一個決議為輸入 Promise 結果陣列的單個 Promise。當所有輸入的承諾都已解決,或者輸入可迭代物件不包含承諾時,此回傳的承諾將解決。它會在任何輸入承諾拒絕或非承諾拋出錯誤時立即拒絕,并將拒絕此第一個拒絕訊息/錯誤。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
uj5u.com熱心網友回復:
在您的示例中,我注意到您不會解決 Promise:
代替
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
}, 20000);
嘗試
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
resolve(true); // or any value
}, 20000);
uj5u.com熱心網友回復:
Promise.all是要走的路,但你需要resolve兌現你的承諾
const logger = console;
const functionOne = function () {
logger.info("Starting functionOne");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
resolve(); // need to resolve
}, 20000);
});
};
const functionTwo = function () {
logger.info("Starting functionTwo");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionTwo after 10 sec.");
resolve();
}, 10000);
});
};
Promise.all([functionOne(), functionTwo()]).then(() => {
logger.info(`All done after 20 sec.`);
});
uj5u.com熱心網友回復:
最好共享一個 jsfiddle /working 代碼以加快除錯速度。這是您的參考的有效解決方案。
希望下面的 JS 小提琴有幫助。 https://jsfiddle.net/xqjvtypb/
const functionOne = function () {
logger.info("Starting functionOne");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionOne after 20 sec.");
}, 20000);
});
};
const functionTwo = function () {
logger.info("Starting functionTwo");
return new Promise(resolve => {
setTimeout(function () {
logger.info("Finished functionTwo after 10 sec.");
}, 10000);
});
};
const runningFunctions = async function () {
logger.info('Start jobs');
Promise.all([functionOne(), functionTwo()]).then(() => {
logger.info(`All done after 20 sec.`);
});
/* functionOne() */;
/* functionTwo() */;
}
runningFunctions().then(()=>{
// No action required.
});
uj5u.com熱心網友回復:
您的主要功能應如下所示:
const runningFunctions = async function () {
logger.info('Start jobs');
await functionOne();
await functionTwo();
logger.info(`All done after 20 sec.`);
}
如果你不想等到另一個函式解決你需要使用 async/await
更多在這里
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/364993.html
標籤:javascript 节点.js 异步 承诺
