Search code examples
node.jsdebuggingasync-awaittry-catchnode-promisify

NodeJS: Await Skips Catch Block and Exits Function. Why?


this is my first question so give me feedback please.

The file in question is a very large file so I am thinking to use asynchronous reading.

Expected behavior:

Success: "await" will cause the execution of the code to block until the file has been read.

Error: Even if the await fails, any error should be caught by the catch block. The console.log() should indicate that it's being caught.

Observed: The await fails, and the catch block is skipped completely, and execution resumes on the next line of Main. The entire async function is skipped. In the debugger, I can see that the right output in result comes out for just a split second and then it goes straight out of the function.

Can someone please tell me why this is happening and how I can fix it? It was my understanding that if an exception happens, the catch block will always catch it. Please explain in as much detail and clarity as you can, I am still trying to grasp the NodeJS language.

The line that was commented out was another way I thought to do the same task. It also suffers from the same problem. It even skipped a "finally" block when I had one in there too.

Additionally, the "c" variable in Main is a 'pending' promise in the debugger.

Finally, the overall purpose of this code is to parse a JSON file in text form. This is just a MVCE of the bigger file.

const fs = require('fs');
const util = require('util');

async function uploadFile(fileName) {
    try {
        const readFile = util.promisify(fs.readFile);
        result = await readFile(fileName, 'utf-8');
        //result = await fs.readFileSync(fileName, 'utf-8');
        jsonObj = JSON5.parse(result);
    }
    catch (err) {
        console.log(err);
    }
}

function Main() {
    fileName = './Diagnostics_Data_Analysis/AddingToDynamoDB/diag.txt';
    var c = uploadFile(fileName);
    console.log("Done");
    process.exit(0);
}

Main();

Solution

  • await does not block. It suspends execution of the local function and that function, then immediately returns a promise. The caller needs to use that promise to know when the operation is done. You are actually calling process.exit() before your file read has finished. What is happening here is this:

    1. Your code executes await readFile(fileName, 'utf-8'); and the uploadFile() function is suspended and immediately returns a promise.
    2. console.log("Done") runs
    3. process.exit(0) runs.
    4. The file has not yet been read yet and your program has exited.

    Instead, you can do something like this:

    async function Main() {
        const fileName = './Diagnostics_Data_Analysis/AddingToDynamoDB/diag.txt';
        const c = await uploadFile(fileName);
        console.log("Done");
        process.exit(0);
    }
    

    This will wait for the uploadFile() function to actually notify completion before calling process.exit(0).

    P.S. Nodejs now has promise versions of the fs library built in already, so you can use fs.promises.readFile() and don't have to make your own promisified version of that.