1

My intention is to dispatch a number of filesystem related tasks that will run in parallel. I save them as promises, which I await later, having given them some time to work. Unfortunately, when I await another unrelated promise any error from one of my filesystem promises is thrown at that point.

The example below illustrates this. An uncaught error is thrown at the line await sleep(1000).

How can I accomplish what I need to do?

function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) }

async function work() {
    const p1 = new Promise((resolve, reject) => reject("p1 reject"))
    const p2 = new Promise((resolve, reject) => resolve("p2 resolve"))

    console.log("Sleeping")
    await sleep(1000)

    console.log("Awaiting p2")
    console.log("result", await p2)

    console.log("Awaiting p1")
    try {
        console.log("result", await p1)
    } catch (error) {
        console.log("caught:", error)
    }
}

work()
PS C:\test> node --version
v16.17.0
PS C:\test> node .\promise-error-handling.js
Sleeping
node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "p1 reject".] {
  code: 'ERR_UNHANDLED_REJECTION'
}
PS C:\test> 

The problem occurs even if using Promise.all

function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) }

async function work() {
    const p1 = new Promise((resolve, reject) => reject("p1 reject"))
    const p2 = new Promise((resolve, reject) => resolve("p2 resolve"))

    try {
        console.log("Sleeping")
        await sleep(1000)
    } catch (error) {
        console.log("caught sleep", error)
    }

    try {
        await Promise.all([p1, p2])
    } catch (error) {
        console.log("caught:", error)
    }
}

work()
Sleeping
node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "p1 reject".] {
  code: 'ERR_UNHANDLED_REJECTION'
}
nneil
  • 11
  • 2
  • "*I save them as promises, which I await later*" - yeah, don't do that, use `Promise.all` instead. `p1` is rejected but not handled immediately, causing an `UnhandledPromiseRejection`. – Bergi Oct 03 '22 at 15:26
  • "*The problem occurs even if using Promise.all*" - yes of course, you still have two sequential `await`s in your code. You'll need to write `const p3 = sleep(1000)` and only `await Promise.all([p1, p2, p3])` together at once. – Bergi Oct 18 '22 at 20:20
  • Are you saying that no Javascript programs can have sequential awaits? – nneil Oct 19 '22 at 11:13
  • No, they're fine in general, but you must not start the an action without immediately `await`ing it. You can also move the `await sleep(1000)` either *before* constructing `p1` and `p2`, or *after* the `await Promise.all([p1, p2])`. – Bergi Oct 19 '22 at 18:11

0 Answers0