Ответ Беньямина предлагает отличную абстракцию для решения этой проблемы, но я надеялся на менее абстрактное решение. Явный способ разрешить эту проблему - просто вызвать .catch
во внутренних обещаниях и вернуть ошибку из своего обратного вызова.
let a = new Promise((res, rej) => res('Resolved!')),
b = new Promise((res, rej) => rej('Rejected!')),
c = a.catch(e => { console.log('"a" failed.'); return e; }),
d = b.catch(e => { console.log('"b" failed.'); return e; });
Promise.all([c, d])
.then((result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
.catch(err => console.log('Catch', err));
Promise.all([a.catch(e => e), b.catch(e => e)])
.then(result => console.log('Then', result)) // Then ["Resolved!", "Rejected!"]
.catch(err => console.log('Catch', err));
Сделав этот шаг дальше, вы можете написать общий обработчик улов, который выглядит следующим образом:
const catchHandler = error => ({ payload: error, resolved: false });
, тогда вы можете сделать
> Promise.all([a, b].map(promise => promise.catch(catchHandler))
.then(results => console.log(results))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!', { payload: Promise, resolved: false } ]
. Проблема заключается в том, что пойманные значения будут иметь другой интерфейс, но вы можете сделать это:
> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
.then(results => console.log(results.filter(result => result.resolved))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]
Затем, чтобы сохранить его, вы получите к ответу Вениамина:
const reflect = promise => promise
.then(successHandler)
.catch(catchHander)
, где он теперь выглядит как
> Promise.all([a, b].map(result => result.then(successHandler).catch(catchHandler))
.then(results => console.log(results.filter(result => result.resolved))
.catch(() => console.log('Promise.all failed'))
< [ 'Resolved!' ]
. Преимущества второго решения - это его абстракция и СУХИЕ. Недостатком является то, что у вас больше кода, и вы должны помнить, что должны отражать все ваши обещания, чтобы сделать их согласованными.
Я бы охарактеризовал свое решение как явное и KISS, но действительно менее надежное. Интерфейс не гарантирует, что вы точно знаете, было ли обещание успешным или неудачным.
Например, у вас может быть следующее:
const a = Promise.resolve(new Error('Not beaking, just bad'));
const b = Promise.reject(new Error('This actually didnt work'));
Этого не поймает a.catch
, поэтому
> Promise.all([a, b].map(promise => promise.catch(e => e))
.then(results => console.log(results))
< [ Error, Error ]
Невозможно сказать, какой из них был фатальным, а какой - нет. Если это важно, тогда вам нужно будет обеспечить соблюдение и интерфейс, который отслеживает, было ли это успешным или нет (что делает reflect
).
Если вы просто хотите обработать ошибки изящно, тогда вы можете просто обрабатывать ошибки как неопределенные значения:
> Promise.all([a.catch(() => undefined), b.catch(() => undefined)])
.then((results) => console.log('Known values: ', results.filter(x => typeof x !== 'undefined')))
< [ 'Resolved!' ]
В моем случае мне не нужно знать ошибку или как она потерпела неудачу - мне просто важно, есть ли у меня значение или нет. Я позволю функции, которая генерирует обещание, беспокоится о регистрации конкретной ошибки.
const apiMethod = () => fetch()
.catch(error => {
console.log(error.message);
throw error;
});
Таким образом, остальная часть приложения может игнорировать свою ошибку, если она захочет, и рассматривать ее как неопределенное значение если он хочет.
Я хочу, чтобы мои функции высокого уровня терпели неудачу и не беспокоились о деталях, почему его зависимости не удались, и я также предпочитаю KISS DRY, когда мне нужно сделать этот компромисс - который в конце концов, почему я решил не использовать reflect
.
Вы подключаетесь к неверной базе данных - ORCLDB.localdomain является службой для базы данных CONTAINER.
Вы сделали, измените контейнер набора сеансов = ORCLPDB1 =>, это база данных, к которой вы хотите подключиться, поэтому попробуйте
sqlplus BUS/DEMO_PASS@localhost:1529/ORCLPDB1
Также, если вы ищете более удобный для пользователя CLI для Oracle Построим SQLcl .