JavaScript等到所有诺言都完成,即使有些诺言被拒绝

JavaScript等到所有诺言都完成,即使有些诺言被拒绝,第1张

JavaScript等到所有诺言都完成,即使有些诺言被拒绝

解决此问题的明确方法是简单地调用

.catch
内部promise,然后从其回调中返回错误

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 } ]

这样做的问题在于,捕获的值将具有与非捕获的值不同的接口,因此要清理此问题,您可以执行以下 *** 作:

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!' ]

然后将其保持干燥,您会得到本杰明的答案:

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!' ]

就我而言,我不需要知道错误或失败的方式,我只是在乎我是否有价值。我将让生成promise的函数担心记录特定错误。

const apiMethod = () => fetch()  .catch(error => {    console.log(error.message);    throw error;  });

这样,应用程序的其余部分可以根据需要忽略其错误,并在需要时将其视为未定义的值。

我希望我的高级函数能够安全地失败,而不必担心其依赖项失败的原因的细节,并且在必须进行权衡时,我也更喜欢KISS而不是DRY,这最终就是为什么我选择不使用

reflect



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5014424.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-14
下一篇 2022-11-14

发表评论

登录后才能评论

评论列表(0条)

保存