赶快承诺拒绝 [英] Catch Promise rejection at a later time

查看:87
本文介绍了赶快承诺拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在以后检索承诺的结果?在测试中,我在发送进一步请求之前检索电子邮件:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆