У меня есть массив Обещаний, с которыми я разрешаю Promise.all(arrayOfPromises);
Я продолжаю цепочку обещаний. Выглядит примерно так
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler();
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Я хочу добавить оператор catch для обработки отдельного обещания в случае ошибки, но когда я пытаюсь, Promise.all
возвращает первую найденную ошибку (игнорирует остальные), а затем я не могу получить данные из остальных обещаний в массив (это не ошибка).
Я пытался сделать что-то вроде ..
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler()
.then(function(data) {
return data;
})
.catch(function(err) {
return err
});
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Но это не решает.
Спасибо!
-
Редактировать:
То, что сказано ниже, было полностью правдой, код нарушался по другим причинам. На случай, если кому-то интересно, это решение, которое я выбрал ...
Серверная цепочка Node Express
serverSidePromiseChain
.then(function(AppRouter) {
var arrayOfPromises = state.routes.map(function(route) {
return route.async();
});
Promise.all(arrayOfPromises)
.catch(function(err) {
// log that I have an error, return the entire array;
console.log('A promise failed to resolve', err);
return arrayOfPromises;
})
.then(function(arrayOfPromises) {
// full array of resolved promises;
})
};
Вызов API (вызов route.async)
return async()
.then(function(result) {
// dispatch a success
return result;
})
.catch(function(err) {
// dispatch a failure and throw error
throw err;
});
Помещение .catch
for Promise.all
перед тем, .then
как кажется, послужило цели отлова любых ошибок из исходных обещаний, но затем возврата всего массива следующему.then
Спасибо!
.then(function(data) { return data; })
может быть полностью опущенthen
или,catch
и внутри выдается ошибка. Кстати, этот узел?Ответы:
Promise.all
это все или ничего. Он разрешает один раз все разрешения в массиве или отклоняет их, как только одно из них отклоняется. Другими словами, он либо разрешается с помощью массива всех разрешенных значений, либо отклоняется с одной ошибкой.В некоторых библиотеках есть что-то под названием
Promise.when
, которое, как я понимаю, вместо этого будет ожидать разрешения или отклонения всех обещаний в массиве, но я не знаком с этим, и его нет в ES6.Ваш код
Я согласен с другими здесь, что ваше исправление должно работать. Он должен разрешаться с помощью массива, который может содержать смесь успешных значений и объектов ошибок. Необычно передавать объекты ошибок в успешном пути, но, предполагая, что ваш код ожидает их, я не вижу проблем с этим.
Единственная причина, по которой я могу придумать, почему он «не разрешается», заключается в том, что происходит сбой в коде, который вы нам не показываете, и причина, по которой вы не видите никаких сообщений об ошибках, заключается в том, что цепочка обещаний не заканчивается окончательным поймать (насколько вы показываете нам в любом случае).
Я взял на себя смелость вычленить «существующую цепочку» из вашего примера и завершить цепочку ловушкой. Это может быть неправильно для вас, но для людей, читающих это, важно всегда либо возвращать, либо прерывать цепочки, либо потенциальные ошибки, даже ошибки кодирования, будут скрыты (что, как я подозреваю, произошло здесь):
источник
Promise.allSettled()
с достойной поддержкой. Смотрите ссылку .Promise.all
терпит неудачу, когда первый поток терпит неудачу. Но, к сожалению, все остальные потоки продолжают работать, пока не завершат работу. Ничто не отменяется, даже хуже: нет возможности отменить поток вPromise
. Таким образом, что бы потоки ни делали (и не манипулировали), они продолжают, они меняют состояния и переменные, они используют CPU, но в конце они не возвращают свой результат. Вы должны знать об этом, чтобы не создавать хаос, например, когда вы повторяете / повторяете вызов.НОВЫЙ ОТВЕТ
API БУДУЩЕГО Promise
источник
e
не должно бытьError
. Это может быть строка, например, если кто-то возвращает ее какPromise.reject('Service not available')
..then()
и.catch()
.Promise.resolve()
передаст значение первому, аPromise.reject()
передаст последнему. Вы можете обернуть их в объект, например:p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e}))
.Чтобы продолжить
Promise.all
цикл (даже когда Promise отклоняется), я написал служебную функцию, которая вызываетсяexecuteAllPromises
. Эта служебная функция возвращает объект сresults
иerrors
.Идея состоит в том, что все Обещания, которые вы передаете,
executeAllPromises
будут заключены в новое Обещание, которое всегда разрешается. Новое обещание разрешается с массивом, который имеет 2 места. Первое место содержит разрешающее значение (если оно есть), а второе - ошибку (если отклоненное обещание отклонено).В качестве последнего шага команда
executeAllPromises
накапливает все значения упакованных обещаний и возвращает конечный объект с массивом дляresults
и массивом дляerrors
.Вот код:
источник
ES2020 представляет новый метод для типа Promise:
Promise.allSettled()
Promise.allSettled дает вам сигнал, когда все входные обещания выполнены, что означает, что они либо выполнены, либо отклонены. Это полезно в тех случаях, когда вас не интересует состояние обещания, вы просто хотите знать, когда работа выполнена, независимо от того, была ли она успешной.
Подробнее читайте в блоге v8 https://v8.dev/features/promise-combinators
источник
Как сказал @jib,
Тем не менее, вы можете контролировать некоторые обещания, которые «разрешены», и мы хотели бы перейти к
.then
.Например.
источник
если вы используете библиотеку q https://github.com/kriskowal/q, у нее есть метод q.allSettled (), который может решить эту проблему, вы можете обработать каждое обещание в зависимости от его состояния, либо полное, либо отклоненное, поэтому
источник
q
), было бы более полезно, если бы вы предоставили пример использования, связанный с вопросом. В своем нынешнем виде ваш ответ не объясняет, как эта библиотека может помочь решить проблему.Использование Async await -
здесь одна асинхронная функция func1 возвращает разрешенное значение, а func2 выдает ошибку и возвращает ноль в этой ситуации, мы можем обработать ее так, как мы хотим, и вернуть соответствующим образом.
Вывод - ['func1', ноль]
источник
Для тех, кто использует здесь ES8, вы можете сделать что-то вроде следующего, используя асинхронные функции :
источник
Мы можем обработать отклонение на уровне отдельных обещаний, поэтому, когда мы получим результаты в нашем массиве результатов, индекс массива, который был отклонен, будет
undefined
. Мы можем справиться с этой ситуацией по мере необходимости и использовать оставшиеся результаты.Здесь я отклонил первое обещание, поэтому оно не определено, но мы можем использовать результат второго обещания, который находится в индексе 1.
источник
Вы рассматривали
Promise.prototype.finally()
?Кажется, он предназначен для того, чтобы делать именно то, что вы хотите - выполнить функцию после того, как все обещания будут выполнены (разрешены / отклонены), независимо от того, какие обещания были отклонены.
Из документации MDN :
Этот
finally()
метод может быть полезен, если вы хотите выполнить некоторую обработку или очистку после выполнения обещания независимо от его результата.finally()
Метод очень похож на вызов ,.then(onFinally, onFinally)
однако есть несколько отличий:При создании встроенной функции вы можете передать ее один раз, вместо того, чтобы принудительно либо объявить ее дважды, либо создать для нее переменную.
Обратный вызов finally не получит никаких аргументов, поскольку нет надежных средств определения того, было ли обещание выполнено или отклонено. Этот вариант использования предназначен именно для случаев, когда вас не заботит причина отклонения или ценность выполнения, и поэтому нет необходимости предоставлять ее.
В отличие от
Promise.resolve(2).then(() => {}, () => {})
(который будет разрешен с помощью неопределенного),Promise.resolve(2).finally(() => {})
будет разрешен с 2. Аналогично, в отличиеPromise.reject(3).then(() => {}, () => {})
(который будет выполнен с неопределенным),Promise.reject(3).finally(() => {})
будет отклонен с 3.== Откат ==
Если ваша версия JavaScript не поддерживает,
Promise.prototype.finally()
вы можете использовать этот обходной путь от Джейка Арчибальда :Promise.all(promises.map(p => p.catch(() => undefined)));
источник
Promises.allSettled()
он фактически не будет реализован (это задокументировано MDN здесь ), тогдаPromises.all.finally()
, похоже, будет достигнуто то же самое. Я собираюсь дать ему попытку ...allSettled()
.allSettled()
нигде не реализовано (пока), поэтому я не хочу опережать реальность. У меня был успехPromises.all(myPromiseArray).finally()
, и это соответствует этому ответу. Когда онallSettled()
действительно существует, я могу проверить его и выяснить, как он на самом деле работает. До тех пор, кто знает, что на самом деле будут реализовывать браузеры? Если у вас нет недавней информации об обратном ...Promise.allSettled
не реализован в Firefox, но, похоже, существует в Chrome. То, что документы говорят, что оно реализовано, не означает, что оно действительно реализовано. Я не собираюсь использовать его в ближайшее время.С другой стороны, если у вас есть случай, когда вам не особенно важны значения разрешенных обещаний, когда есть один сбой, но вы все еще хотите, чтобы они выполнялись, вы можете сделать что-то подобное, что разрешит обещания как обычно, когда все они преуспевают и отклоняются с невыполненными обещаниями, когда любое из них терпит неудачу:
источник
Вы всегда можете обернуть свое обещание, возвращая функции таким образом, чтобы они улавливали сбой и возвращали вместо него согласованное значение (например, error.message), поэтому исключение не будет полностью свернуто до функции Promise.all и отключит ее.
источник
Я нашел способ (обходной путь) сделать это без синхронизации.
Так что, как было упомянуто ранее
Promise.all
, нет ничего.так что ... Используйте обещание, чтобы поймать и заставить решимость.
источник
Вам нужно знать, как определить ошибку в ваших результатах. Если у вас нет ожидаемой стандартной ошибки, я предлагаю вам выполнить преобразование для каждой ошибки в блоке перехвата, которое делает ее идентифицируемой в ваших результатах.
источник
Не лучший способ вести журнал ошибок, но вы всегда можете установить все в массив для promise и сохранить полученные результаты в новых переменных.
Если вы используете graphQL, вам нужно постобработать ответ независимо, и если он не найдет правильную ссылку, это приведет к сбою приложения, сузив суть проблемы.
источник
Вот так и
Promise.all
рассчитано на работу. Если одно обещаниеreject()
, весь метод немедленно терпит неудачу.Есть случаи использования, когда кто-то может захотеть, чтобы
Promise.all
обещания не выполнялись. Чтобы это произошло, просто не используйте никакихreject()
заявлений в своем обещании. Однако, чтобы ваше приложение / скрипт не зависало в случае, если какое-либо одно базовое обещание никогда не получит ответ, вам нужно установить таймаут.источник
reject()
стоит использовать в своем обещании, но что если вам нужно использовать обещания другой библиотеки?Я написал библиотеку npm, чтобы решить эту проблему более красиво. https://github.com/wenshin/promiseallend
устанавливать
2017-02-25 новый API, это не нарушать принципы обещания
--------------------------------
Старый плохой API, не используйте его!
источник
Promise.all
. Но он будет собирать все данные и ошибки каждого обещания. также он поддерживает ввод объекта, это не точка. После сбора всех данных и ошибок я переопределяюpromise.then
метод для обработки зарегистрированных обратных вызовов, в том числе отклоненных и выполненных. Для деталей вы можете увидеть кодonFulfilled
иonRejected
обработчики, которые передаютсяthen
?fulfilled
иrejected
. Но на самом деле это вызывает сложную проблему совместимости со всеми обещанными вариантами использования, какonFulfilled
иonRejected
все возвращаютPromise.reject()
илиPromise.resolve()
. Пока мне не ясно, как ее решить, есть ли у кого идея получше? Лучший ответ на данный момент проблема заключается в том, что он может не фильтровать данные и ошибки в среде браузера.