Выполнены асинхронные операции, связанные с обещаниями. Если одно из этих обещаний отвергается, то Promise.all()
просто не ждет, пока все они будут завершены, он отвергает, когда первое обещание отклоняется. Именно так оно и предназначалось для работы. Если вам нужна другая логика (например, вы хотите дождаться, когда все они будут выполнены, независимо от того, выполняют ли они или отклоняют), тогда вы не можете использовать только Promise.all()
.
Помните, что обещание - это не сама операция async. Обещание - это просто объект, который отслеживает состояние операции async. Итак, когда вы передаете массив обещаний Promise.all()
, все эти асинхронные операции уже запущены и все уже в полете. Они не будут остановлены или отменены.
Почему Promise.all отказывается от обещаний, если кто-либо из них отвергает, так как я ожидаю, что он будет ждать «всех» обещаний.
Это работает так, как это сделано, потому что именно так оно и было разработано, и это очень распространенный случай использования, когда вы не хотите, чтобы ваш код продолжался, если была какая-либо ошибка. Если это не будет вашим прецедентом, тогда вам нужно использовать некоторую реализацию .settle()
, у которой есть поведение, которое вы хотите (что, как вам кажется, уже известно).
Что я нахожу более интересным вопросом, почему нет опции .settle()
в спецификации и стандартной реализации, так как это также довольно распространенный вариант использования. К счастью, как вы нашли, кода не так много, чтобы сделать свой собственный. Когда мне не нужно фактической причины отказа и просто хотите некоторое значение индикатора, чтобы быть помещены в массив, я часто использую это довольно простой в использовании версии:
// settle all promises. For rejeted promises, return a specific rejectVal that is
// distinguishable from your successful return values (often null or 0 or "" or {})
Promise.settleVal = function(rejectVal, promises) {
return Promise.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return Promise.resolve(p).catch(function(err) {
// instead of rejection, just return the rejectVal (often null or 0 or "" or {})
return rejectVal;
});
}));
};
// sample usage:
Promise.settleVal(null, someArrayOfPromises).then(function(results) {
results.forEach(function(r) {
// log successful ones
if (r !== null) {
console.log(r);
}
});
});
что именно означает «отбрасывать» означает?
Это просто означает, что обещания больше не отслеживаются Promise.all()
. Асинхронные операции, с которыми они связаны, всегда сохраняют право делать то, что они собираются делать.И на самом деле, если эти обещания имеют на них обработчики .then()
, они будут вызваны так, как обычно. discard
выглядит как неудачный термин для использования здесь. Ничто не происходит, кроме Promise.all()
, перестает обращать на них внимание.
FYI, если я хочу более надежную версию .settle()
, которая отслеживает все результаты и отклонять причины, то я использую это:
// ES6 version of settle that returns an instanceof Error for promises that rejected
Promise.settle = function(promises) {
return Promise.all(promises.map(function(p) {
// make sure any values or foreign promises are wrapped in a promise
return Promise.resolve(p).catch(function(err) {
// make sure error is wrapped in Error object so we can reliably detect which promises rejected
if (err instanceof Error) {
return err;
} else {
var errObject = new Error();
errObject.rejectErr = err;
return errObject;
}
});
}));
}
// usage
Promise.settle(someArrayOfPromises).then(function(results) {
results.forEach(function(r) {
if (r instanceof Error) {
console.log("reject reason", r.rejectErr);
} else {
// fulfilled value
console.log("fulfilled value:", r);
}
});
});
Это решает массив результатов. Если результатом является instanceof Error, тогда он был отклонен, иначе это выполнимое значение.
Вопросы, которые задают «почему это не спроектировано так, как я хочу» редко (возможно, никогда), не дают удовлетворительного ответа. Ответ почти всегда: «потому что дизайнер думал, что другой способ более полезен». Это было их мнение. У вас есть ваше мнение. Они не всегда будут совпадать. – jfriend00
@ jfriend00 Нет ни одного дизайнера. Спекуляции прибывают на основе консенсуса. Я думаю, что есть веские причины. SO не может быть лучшим местом для автоответчиков, хотя, если вы не захотите прорыть минуты. – jib
Слово «отбросить», используемое в статье MDN, является неудачным. Вероятно, «игнорировать» или «не беспокоиться», или «не делать ничего дальше», было бы лучшим выбором слов. Исправлена. В любом случае, вы говорите * Вместо этого я должен использовать взломать вот так *. Почему вы называете это взломом? –