赶快承诺拒绝 [英] Catch Promise rejection at a later time
问题描述
如何在以后检索承诺的结果?在测试中,我在发送进一步请求之前检索电子邮件:
How do I retrieve the result of a promise at a later time? In a test, I am retrieving an email before sending further requests:
const email = await get_email();
assert.equal(email.subject, 'foobar');
await send_request1();
await send_request2();
如何在慢速邮件检索过程中发送请求?
How can I send the requests while the slow email retrieval is going on?
首先,我考虑稍后等待电子邮件:
At first, I considered awaiting the email later:
// This code is wrong - do not copy!
const email_promise = get_email();
await send_request1();
await send_request2();
const email = await email_promise;
assert.equal(email.subject, 'foobar');
如果 get_email()
成功,则此方法有效,但是如果 get_email()
在相应的 await
之前失败,但是完全合理的 UnhandledPromiseRejectionWarning,则会失败
。
This works if get_email()
is successful, but fails if get_email()
fails before the corresponding await
, with a completely justified UnhandledPromiseRejectionWarning
.
当然,我可以使用 Promise.all
,如下所示:
Of course, I could use Promise.all
, like this:
await Promise.all([
async () => {
const email = await get_email();
assert.equal(email.subject, 'foobar');
},
async () => {
await send_request1();
await send_request2();
},
]);
然而,它使代码更难阅读(它看起来更像基于回调的编程),特别是如果以后的请求实际上依赖于电子邮件,或者有一些嵌套正在进行中。是否可以存储承诺的结果/例外,等待
以后呢?
However, it makes the code much harder to read (it looks more like callback-based programming), especially if later requests actually depend on the email, or there is some nesting going on. Is it possible to store the result/exception of a promise and await
it at a later time?
如果需要是的,这是一个测试案例,其中的模拟有时会失败,有时会随机计时。它必须永远不会输出 UnhandledPromiseRejectionWarning
。
If need be, here is a testcase with mocks that sometimes fail and sometimes work, with random timings. It must never output UnhandledPromiseRejectionWarning
.
推荐答案
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const send_request1 = () => wait(300), send_request2 = () => wait(200);
async function get_email() {
await wait(Math.random() * 1000);
if (Math.random() > 0.5) throw new Error('failure');
return {subject: 'foobar'};
}
const assert = require('assert');
async function main() {
// catch possible error
const email_promise = get_email().catch(e => e);
await send_request1();
await send_request2();
// wait for result
const email = await email_promise;
// rethrow eventual error or do whatever you want with it
if(email instanceof Error) {
throw email;
}
assert.equal(email.subject, 'foobar');
};
(async () => {
try {
await main();
} catch(e) {
console.log('main error: ' + e.stack);
}
})();
这篇关于赶快承诺拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!