In case my Node.js v.13.12 app faces some technical issue, I'd like:
To achieve such behaviour I use the following code:
const onError = async function onError(error) {
await logger.log("Critical error: " + error);
process.exit(UNCAUGHT_FATAL_EXCEPTION);
}
The problem is that when I execute the code above, I reach await logger.log(…)
, go inside and then immediately continue to process.exit(UNCAUGHT_FATAL_EXCEPTION)
and execute it.
As a result, the app is getting closed before the writing to the DB is finished, although I expect from await
to wait until the logger.log(…)
is done.
How to ensure that process.exit(UNCAUGHT_FATAL_EXCEPTION)
will be executed only after logger.log(…)
is done without using a callback?
Update:
The entire logger.log(…)
code-chain:
export const log = async function log(source, severityNum, severityLevel, limitSeverityNum, functionName, message) {
if ((severityNum > LOG_LEVELS.OFF.intLevel) && (severityNum <= limitSeverityNum)) {
await writeLogToDB(source, severityNum, severityLevel, functionName, message);
}
};
const writeLogToDB = async function writeLogToDB(source, severityNum, severityLevel, functionName, message) {
try {
const con = await getConnection();
con.connect(function (err) {
if (err) throw err;
con.query(qryDict.QUERIES.setAddNewLog, [source, severityNum, severityLevel, functionName, message], function (err) {
try {
if (err) {
console.error("addNewLog", err);
}
let response = JSON.stringify({
"result": true,
"message": "success"
});
} catch (err) {
let response = JSON.stringify({
"result": false,
"message": err
});
return response;
} finally {
con.close();
}
});
});
} catch (err) {
con.close();
console.error(err);
}
};
The problem is in the writeLogToDB
function.
The function is async, but internally it uses the con.connect
callback-based mechanism, which no code is await-ing on.
You have to use promises all the way for the await
-ing to propagate:
const writeLogToDB = async function writeLogToDB(
source,
severityNum,
severityLevel,
functionName,
message
) {
const con = await getConnection();
return new Promise((resolve, reject) => {
con.connect(function(err) {
if (err) return reject(err);
con.query(
qryDict.QUERIES.setAddNewLog,
[source, severityNum, severityLevel, functionName, message],
function(err) {
if (err) return reject(err);
resolve(
JSON.stringify({
result: true,
message: "success"
})
);
}
);
});
}).finally(() => {
// note: add a check here to do it only
// if connection is opened to handle edge cases
con.close();
});
};
A cleaner solution would be to implement the connection methods themselves to be promise-based, not callback. (maybe util/promisify can help)
Then you'd have cleaner code:
const writeLogToDB = async function writeLogToDB(
source,
severityNum,
severityLevel,
functionName,
message
) {
const con = await getConnection();
try {
await con.connect();
await con.query(qryDict.QUERIES.setAddNewLog, [
source,
severityNum,
severityLevel,
functionName,
message
]);
return JSON.stringify({
result: true,
message: "success"
});
} finally {
// note: add a check here to do it only
// if connection is opened to handle edge cases
con.close();
}
};