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