Проблема в том, что, как только один await
ed Promise
отклоняет запрос, выдается ошибка, и код перемещается из строки await brokenPromises[0]
внутри try
в catch
.Итак, ошибка, выданная brokenPromises[0]
, теперь правильно перехвачена.Но отклоненный Promise
в brokenPromises[1]
не был обработан!(Это было бы обработано , если бы блок try
прошел [0]
и достиг [1]
, а затем await brokenPromises[0]
вызвал бы ошибку, которая была бы обнаружена, но интерпретаторне знает этого)
Вот гораздо меньший пример, иллюстрирующий исходную проблему (откройте консоль браузера, чтобы увидеть отклонение, оно не отображается в консоли Stack Snippet):
const makeProm = () => new Promise((_, reject) => setTimeout(reject, 500));
console.log('will be uncaught:');
// Unhandled rejection:
(async () => {
try {
const proms = [makeProm(), makeProm()];
await proms[0];
await proms[1];
} catch(e){}
})();
// Works:
setTimeout(async () => {
console.log('going to be caught:');
try {
await makeProm();
await makeProm();
} catch(e){ console.log('caught'); }
}, 1000);
Вы можете исправить это, await
используя Promise.all
из обоих Promise
с вместо await
каждого Promise
по отдельности - таким образом,когда выбрасывается Promise.all
, обе отклоненные цепочки Promise
были обработаны.
Изменение здесь process.stdout.write
s на console.log
s, чтобы исправить это, можно было показать в исполняемом фрагменте:
const DEMONSTRATE_FAILURE = true;
async function doPromises() {
try {
if (DEMONSTRATE_FAILURE) {
// This causes UnhandledPromiseRejectionWarning warnings:
const brokenPromises = [createPromises(), createPromises()]
await Promise.all(brokenPromises);
} else {
// This works fine:
await createPromises()
await createPromises()
}
} catch (err) {
console.log("x")
}
}
// Create 10 promises, of which 50% will reject after between 0 and 1000ms
function createPromises() {
let badPromises = []
for (let x = 0; x < 10; x++) {
badPromises.push(new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
console.log("-")
reject("rejected!")
} else {
console.log("+")
resolve()
}
}, Math.round(Math.random() * 1000))
}))
}
return Promise.all(badPromises)
}
(async function main() {
await doPromises()
})()