I've been studying a lot on asynchronous javascript, from callbacks to promises to async/await.
Now I'm having a hard time understanding why do I lose control over error handling in the following code sample. I've even dived into Node's source code, but that gave me more trouble than answers.
This is what I do:
const { readFile } = require('node:fs') process.on('uncaughtExceptionMonitor', (error, origin) => { console.log('\nuncaughtExceptionMonitor handler: {') console.log(`ERROR: ${error}`) console.log(`ORIGIN: ${origin}`) console.log('}\n') }) try { readFile('./jsconfig.json', 'utf8', (err, res) => { if (err) console.log('failed to read file') if (res) console.log('successfully read file') throw new Error(`THROWN BY BUILT-IN FUNCTION'S CALLBACK`) //error thrown }) } catch (error) { console.log(`error caught by readFile's outer scope`) // not caught here }
When run, it gives me the following result:
successfully read file
uncaughtExceptionMonitor handler: { ERROR: Error: THROWN BY BUILT-IN FUNCTION'S CALLBACK ORIGIN: uncaughtException }
C:\Users\Heavy\Documents\dev\hwoarang\leg.js:15 throw new Error(
THROWN BY BUILT-IN FUNCTION'S CALLBACK) //error thrown ^Error: THROWN BY BUILT-IN FUNCTION'S CALLBACK at C:\Users\Heavy\Documents\dev\hwoarang\leg.js:15:11 at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3)
This is my first question so I'm not quite comfortable with Stackoverflow's formatting. I apologize for that.
Can you help me?
try...catch applies to the code that runs synchronously in the try block. The callback given to the readFile function, does not execute synchronously, but after the try block has completed execution (and all synchronous code that follows it until the call stack has been emptied and the job queue(s) are processed by the engine). Once execution completes the try block, it can never happen to still get in the catch block later.
Later, a new execution context is created where the callback is executed. This execution context knows nothing about this try..catch block.
You can make use of the promise version of fs:
const { promises: { readFile } } = require("fs");
async function test() {
try {
const res = await readFile('./jsconfig.json', 'utf8');
console.log('successfully read file');
throw new Error(`THROWN AFTER AWAIT`) //error thrown
} catch (error) {
console.log(`error caught`) // will be caught
}
}
test();
Here, with await, the try block is suspended together with the function's execution context. Once the awaited promise is resolved, that function context is restored with its unfinished try block, and then execution continues within that block, so that an error will be caught and make the catch block execute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With