Проблема в том, что в момент отклонения вызова rej
интерпретатор еще не дошел до строки, которая await
является обещанием, созданным rej
, поэтому отклоненное обещание - это просто отклоненное Обещание, а не Обещание, что текущий поток await
ing :
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
Итак, поведение такое же, как если бы отклоненное обещание было объявлено без обработчика catch
. (Ошибки, выданные Обещаниями, будут обнаружены в функции async
, только если они await
ed в точке, в которой Обещание отклоняет - в противном случае это просто приведет к необработанному отклонению обещания .)
Я бы предложил объявить Обещания в тот же момент, что и вы await
: 1018 *
const data1 = await res(3000)
(примечание: время вышеописанного метода не будет таким же, как у исходного кода)
или используйте await Promise.all
для всех Обещаний, что означает, что Promise
переводчик в настоящий момент await
ing сгенерирует (и тем самым войдет в блок catch
), как только one из Обещания отклоняются:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
Чтобы выполнить дополнительную работу, пока выполняются три Обещания, и отловить ошибки из этих Обещаний, а также из основного потока, передайте четвертый элемент в Promise.all
, IIFE, который выполняет дополнительное работа, которую вы хотите сделать:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()