Benjamin의 답변은이 문제를 해결하기위한 훌륭한 추상화를 제공하지만 덜 추상화 된 솔루션을 원했습니다. 이 문제를 해결하는 명시적인 방법은 단순히 .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));
한 단계 더 나아가 다음과 같은 일반적인 catch 처리기를 작성할 수 있습니다.
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 } ]
이 문제는 catch 된 값이 catch되지 않은 값과 다른 인터페이스를 가지므로이를 정리하기 위해 다음과 같은 작업을 수행 할 수 있습니다.
const successHandler = result => ({ payload: result, resolved: true });
이제 당신은 이것을 할 수 있습니다 :
> 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!' ]
그런 다음 DRY를 유지하려면 Benjamin의 답변을 얻습니다.
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!' ]
두 번째 솔루션의 장점은 추상화되어 DRY라는 것입니다. 단점은 더 많은 코드가 있으며 일을 일관성있게 만들기 위해 모든 약속을 반영해야한다는 것입니다.
내 솔루션을 명시 적 및 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
.