【问题标题】:Transaction Complete Err when calling async function within async function在异步函数中调用异步函数时事务完成错误
【发布时间】:2018-08-20 13:02:26
【问题描述】:

我有以下异步函数来复制名为“问卷”的 postgres 数据库表中的记录:

const duplicateQuestionnaire = async(trx, originalQuestionnaireId) => {
  const originalQuestionnaire = await trx
    .select("*")
    .from("Questionnaires")
    .where({
      id: originalQuestionnaireId
    })
    .then(head);

  const newQuestionnaireId = await trx
    .table("Questionnaires")
    .insert(omit(originalQuestionnaire, "id"))
    .returning("id")
    .then(head);

  const sectionIDs = await trx
    .select("id")
    .from("Sections")
    .where({
      QuestionnaireId: originalQuestionnaireId
    });

  sectionIDs.map(element => {
    duplicateSection(trx, element.id, newQuestionnaireId);
  });

  return trx
    .select("*")
    .from("Questionnaires")
    .where({
      id: newQuestionnaireId
    })
    .then(head);
};

复制后,它将调用第二个异步函数来复制名为“Sections”的表中的记录:

const duplicateSection = async (trx, sectionId, newQuestionnaireId) => {
  const originalSection = await trx
    .select("*")
    .from("Sections")
    .where({ id: sectionId })
    .then(head);

  const newSection = omit(originalSection, "id");

  newQuestionnaireId ? (newSection.QuestionnaireId = newQuestionnaireId) : null;

  const newSectionId = await trx
    .table("Sections")
    .insert(newSection)
    .returning("id")
    .then(head);

  return trx
    .select("*")
    .from("Sections")
    .where({ id: newSectionId })
    .then(head);
};

这些函数在设计时考虑了层次结构:duplicateQuestionnaire 调用 duplicateSection,因为问卷包含部分。后一个函数可以在不调用前一个的情况下被调用,并且不会将其作为其操作的一部分来调用。

每个函数的返回值作为一个GraphQL返回。

这些函数都对数据库产生了预期的效果;他们工作。但是,duplicateQuestionnaire 正在标记此错误:

(node:172) UnhandledPromiseRejectionWarning: Error: Transaction query already complete, run with DEBUG=knex:tx for more info
web_1  |     at completedError (/app/node_modules/knex/lib/transaction.js:303:9)
web_1  |     at /app/node_modules/knex/lib/transaction.js:277:22
web_1  | From previous event:
web_1  |     at Client_PG.trxClient.query (/app/node_modules/knex/lib/transaction.js:275:34)
web_1  |     at Runner.<anonymous> (/app/node_modules/knex/lib/runner.js:155:36)
web_1  | From previous event:
web_1  |     at /app/node_modules/knex/lib/runner.js:61:21
web_1  |     at runCallback (timers.js:810:20)
web_1  |     at tryOnImmediate (timers.js:768:5)
web_1  |     at processImmediate [as _immediateCallback] (timers.js:745:5)
web_1  | From previous event:
web_1  |     at Runner.run (/app/node_modules/knex/lib/runner.js:47:31)
web_1  |     at Builder.Target.then (/app/node_modules/knex/lib/interface.js:39:43)
web_1  |     at duplicateSection (/app/repositories/DuplicateRepository.js:49:6)
web_1  |     at <anonymous>
web_1  | (node:172) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
web_1  | (node:172) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

我知道问题在于我如何处理 .map() 中的每个 duplicateSection 调用,但是,经过一些研究和深入的谷歌搜索,我仍然在努力解决它。

【问题讨论】:

    标签: javascript node.js asynchronous async-await knex.js


    【解决方案1】:

    你想awaitduplicateSections 返回的所有承诺:

     await Promise.all(sectionIDs.map(element =>
        duplicateSection(trx, element.id, newQuestionnaireId)
     ));
    

    这不仅可以确保在您运行最终查询之前复制所有部分,还可以链接被拒绝的 Promise。

    【讨论】:

    • 干杯!仅供参考,您在最后一行缺少一个右括号。否则,工作就像做梦一样。
    • @matt 很高兴为您提供帮助 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2020-03-09
    • 1970-01-01
    相关资源
    最近更新 更多