0

I cant throw an error properly from a built in async array function, I get the following error - (node:12104) UnhandledPromiseRejectionWarning: Error: non existent item provided

It is clearly something to do with the fact the error is thrown from within the forEach() async function because if I throw it outside of that function it is caught correctly.

Function:

async myFunction(obj) {
    obj.items.forEach(async item => {
        if (itemDict[item]) {
            // do something
        } else {
            throw new Error('non existent item provided');
        }
    });
}

Test:

describe('type.js', async function() {
    it('throws error if non existent item is provided', async function() {
        try {
            const type = new Type();                
            await type.myFunction({
                items: ['item']
            });
            expect.fail('test failed');
        } catch (err) {
            expect(err.message).to.be.equal('non existent item provided');
        }  
    });
});

I have tried wrapping the forEach() in an additional try/catch block but get the same error and the catch block is never triggered.

async myFunction(obj) {
    try {
        obj.items.forEach(async item => {
            if (itemDict[item]) {
                // do something
            } else {
                throw new Error('non existent item provided');
            }
        });
    } catch (err) {
        console.log('caught');
    } 
}

Where am I going wrong?

newprogrammer
  • 600
  • 10
  • 22

2 Answers2

2

You can try with for loop.

like this:

async myFunction(obj) {
    for (const item of obj.items) {
        if (itemDict[item]) {
            // do something
        } else {
            throw new Error('non existent item provided');
        }
    });
}
fro
  • 402
  • 3
  • 8
1

Since "forEach" is not asynchronous, there might be lotta problems using async in it.
If you want to use async in a loop, there is a way of using "for" loop. Or, even better way, as for me, using async in map wrapped in Promise.all.
With that one you will perform all of the promises in parallel since async function returns Promise.

Promise.all(elements.map(async(elem) => elem)));

Here is the link explaining all of the stuff above.