Catch Promise rejection at a later time

  • A+
Category:Languages

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.

 


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);     } })(); 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: