skip to Main Content

I have a node.js script like this (for educational purposes it’s entangled, not actual production code):

const run = new Promise((resolve, reject) => {
    (async () => {
        let cleanup = () => {
            console.log('inside cleanup');
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve();
                }, 5000);
            });
        };

        try {
            throw new Error('error');
        } catch (err) {
            console.log('rejecting')
            reject(err);
        } finally {
            console.log('inside finally')
            await cleanup().then(() => {
                console.log('exiting');
                resolve('done');
            });
        }
    })();
});

run.then((r) => console.log(r));

Based on this answer, I would expect Node to wait and not exit until the promise inside finally is resolved. However, it seems to exit immediately. What am I missing here?

$ node pup
rejecting
inside finally
inside cleanup
D:pup.js:16
            throw new Error('error');
                  ^

I might need to cleanup multiple resources in finally in certain order, so I’d need to wait for completion of previous cleanup actions.

That’s the answer I was looking for:

You are already reject()ing the run promise before the finally block runs, causing an unhandled promise rejection that causes nodejs to exit.

2

Answers


  1. The bit of the linked answer you appear to refer to is about (a) the promise returned from a function using the async keyword when (b) you await a promise inside a try.

    You are doing neither.

    You just call the reject callback inside catch. That’s for a promise that is completely independent of the async IIFE.

    By the time you call resolve you’ve already called reject.

    Login or Signup to reply.
  2. Avoid the Promise constructor antipattern! You are already reject()ing the run promise before the finally block runs, causing an unhandled promise rejection that causes nodejs to exit.

    To fix this, use

    function delay(t) {
        return new Promise((resolve, reject) => {
            setTimeout(resolve, t);
        });
    }
    
    async function run() {
        try {
            throw new Error('error');
        } catch (err) {
            console.log('handling error')
            throw err;
        } finally {
            console.log('cleaning up')
            await delay(5000);
            console.log('exiting');
            // return 'done';
        }
    }
    
    run().then(console.log);
    

    You should avoid returning from a finally block as that would override the exception. If you actually meant to handle the error in the catch block, do not re-throw it:

    async function run() {
        try {
            throw new Error('error');
        } catch (err) {
            console.log('handling error', err.message)
        } finally {
            console.log('cleaning up')
            await delay(5000);
            console.log('exiting');
        }
        return 'done';
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search