簡體   English   中英

如何等待所有 Promise 完成

[英]How to wait for all Promises to be finished

我喜歡並行運行一組函數,當所有函數都完成后,我喜歡運行一些最終的東西。 我的 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.`);

原則上我的日志 output 應該是這個:

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 啟動后立即出現,或者根本不打印最終日志。

我必須如何編寫腳本?

也許你需要Promise.all()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all() 方法將一個可迭代的 Promise 作為輸入,並返回一個 Promise,它解析為輸入 Promise 的結果數組。 這個返回的 promise 將在輸入的所有承諾都已解決,或者輸入可迭代不包含任何承諾時解決。 它會在任何輸入的 promise 被拒絕或 non-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"]

在您的示例中,我注意到您不會解析 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);

首先,您必須同時修復functionOne()functionTwo()以便它們resolve()它們在計時器觸發時創建的 promise。 沒有它,他們只會創建一個永遠不會解決的 promise,這不是很有用,並且在完成時不會通知調用者。

然后,要並行運行它們,請使用Promise.all()這將允許您調用這兩個函數,然后它將一起跟蹤兩個返回的承諾,並且從對 ZA5A3F0F287A448982AAC520CFFEall4779AZ 的調用返回的Promise.all()將在兩個函數完成時解析。如果任一函數拒絕了它們的 promise,則拒絕。

如果您的示例在這里,您的任何承諾都沒有拒絕,但是如果您想知道所有承諾何時完成,即使有些拒絕,那么您將使用Promise.allSettled()而不是Promise.all() The main difference is that Promise.all() will short-circuit and reject it's promise as soon as any promise you pass it rejects, whereas Promise.allSettled() will wait until all promises are done, regardless of resolve/reject. 盡管您沒有在這里使用它,但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每個 function 調用。 這是一個可運行的(在代碼段中)示例:

 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); });

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.`);
});

ES2020 中的新功能是Promise.allSettled

Promise.allSettled()方法返回一個 promise,它在所有給定的承諾都已履行拒絕后解決,其中包含一個對象數組,每個對象都描述每個 promise.

這與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();

最好共享一個 jsfiddle /working 代碼以加快調試速度。 這是您的參考的有效解決方案。

希望下面的 JS fiddle 有所幫助。 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.

});

您的主要 function 應該如下所示:

const runningFunctions = async function () {
  logger.info('Start jobs');
  await functionOne();
  await functionTwo();
  logger.info(`All done after 20 sec.`);
}

如果您不想等到另一個 function 將解決您需要使用 async/await

更多在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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