23

Why the try...catch is not working for below sample code?

const http2 = require("http2")
const url = require("url")


function sendRequest() {
    return new Promise((resolve, reject) => {

        var r = http2.request({
            "host": "www.google.com",
            "method": "GET",
            "path": "/"
        }, (resp) => {
            var data = []
            resp.on("data", (chunk) => {
                throw ("Error")
            })
            resp.on("end", () => {
                console.log("ended")
                resolve("finished")
            })
            resp.on("error", (e) => {
                console.log("error")
                reject(e)
            })
        })
        r.end()
    })
}

async function wrapper(){
    try {
        console.log("Sending request")
        await sendRequest()
        console.log("Finished sending Request")
    }catch(e){
        console.log("error!") // Supposed to see this
        console.log(e)
    }
    console.log("All finished") // Supposed to see this
}

wrapper()

Output is as follow:

Sending request

/Users/test-user/test.js:15
                throw ("Error")
                ^
Error

Process finished with exit code 1
MK Yung
  • 4,344
  • 6
  • 30
  • 35

2 Answers2

13

You can throw inside a promise and catch the error with catch so long as the error is in the promise itself and not in different async callback.

For example, the test() works as expected, but test2() does not:

function test(){
    return new Promise((resolve, reject) => {
        throw (new Error("error"))
    })
}

function test2(){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            throw (new Error("error"))
        }, 100)

    })
}
async function go (){
    try {
        await test()
    } catch(err){
        console.log("caught error from test(): ", err.message)
    }

    try {
        await test2()
    } catch(err){
        console.log("caught error from test2(): ", err.message)
    }

}
go()

Both cases work fine with reject() instead of throw()

Mark
  • 90,562
  • 7
  • 108
  • 148
0

Because throw is only converted to a promise rejection in an async function, the synchronous portion of the promise executor (the callback you pass new Promise), or the synchronous portion of a then or catch callback. You're doing it in a non-async callback, which isn't any of those places.

throw ("Error"); should be reject("Error"); (well, really it should be reject(new Error("Error")); — rejections are errors, so using new Error gives you the stack trace, etc.).


Side note: Normally, receiving the data event wouldn't be an error in any case...

Side note 2: The () in throw ("Error"); do nothing. When throwing is an option, simply throw "Error"; (or, again, throw new Error("Error");).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Having error on chunk, might not be totally weird. Eg, if say downloading a file and you expected to receive a ZIP, you could check the magic code in the first few chunks, and then abort & reject promise. Saves downloading something that's not what your after. – Keith Nov 07 '17 at 17:19
  • @Keith: Sure. But the code in question is unconditional. – T.J. Crowder Nov 07 '17 at 17:20
  • 1
    I think the code in questions is not for real.. :) – Keith Nov 07 '17 at 17:26