如何确保仅在 await-function 完成后才执行代码?

How to ensure a code execution only after the await-function is done?

如果我的 Node.js v.13.12 应用程序遇到一些技术问题,我想:

  1. 在数据库中写入日志消息;
  2. 使用特定代码退出 Node.js 应用程序。

为了实现这种行为,我使用了以下代码:

const onError = async function onError(error) {

    await logger.log("Critical error: " + error);

    process.exit(UNCAUGHT_FATAL_EXCEPTION);
}

问题是当我执行上面的代码时,我到达await logger.log(…),进去然后立即继续process.exit(UNCAUGHT_FATAL_EXCEPTION)并执行。

因此,应用程序在写入数据库之前关闭,尽管我希望 await 等到 logger.log(…) 完成。

我的问题:
如何确保process.exit(UNCAUGHT_FATAL_EXCEPTION)只在logger.log(…)完成后执行而不使用回调?

更新:
整个 logger.log(…) 代码链:

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);
    }
};

问题出在 writeLogToDB 函数中。

该函数是异步的,但它在内部使用 con.connect 基于回调的机制,没有代码正在等待。

您必须一直使用 promises 才能使 await-ing 传播:

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();
  });
};

更简洁的解决方案是将连接方法本身实现为基于承诺,而不是回调。 (也许 util/promisify 可以提供帮助)

那么您将拥有更简洁的代码:

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();
  }
};