Saturday, 22 December 2018

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');

This works if get_email() is successful, but fails if get_email() fails before the corresponding await, with a completely justified UnhandledPromiseRejectionWarning.

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?

If need be, here is a testcase with mocks that sometimes fail and sometimes work, with random timings. It must never output UnhandledPromiseRejectionWarning.



from Catch Promise rejection at a later time

No comments:

Post a Comment