【问题标题】:How to ensure a code execution only after the await-function is done? [duplicate]如何确保只有在等待功能完成后才能执行代码? [复制]
【发布时间】:2020-07-25 07:14:18
【问题描述】:

如果我的 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);
    }
};

【问题讨论】:

  • logger.log 是否返回承诺?
  • 不,它有点像 void 异步函数,只是写入数据库,仅此而已。
  • 你所做的所有await 就是getConnection。您的异步函数不等待回调样式的 con.connectcon.query 调用。在此处使用承诺。
  • 您似乎不需要log()_writeLog()。一个似乎实际上是另一个的同义词。您可以避免捆绑/取消捆绑 args(到 js 对象中),只需编写 export log = _writeLog;
  • @Roamer-1888,好点子。完成。

标签: javascript node.js promise async-await es6-promise


【解决方案1】:

问题出在writeLogToDB 函数中。

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

您必须一直使用 Promise 才能使 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();
  }
};

【讨论】:

  • 感谢代码-sn-p。没错,代码库目前正处于从回调迁移到await/async 的阶段,这就是为什么会出现一些不一致的原因。
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2012-07-01
相关资源
最近更新 更多