在异步函数中调用异步函数时出现事务完成错误
Transaction Complete Err when calling async function within async function
我有以下异步函数来复制名为 'Questionnaires' 的 postgres 数据库 table 中的记录:
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);
};
复制后,它将调用第二个异步函数来复制 table 中名为 '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);
};
These functions are designed with a hierarchy in mind: duplicateQuestionnaire
calls duplicateSection
as a questionnaire contains sections. The latter function can be called without calling the former initially and does not call it as part of its actions.
The return value of each function is used as a GraphQL return.
这两个函数对数据库都有预期的效果;他们工作。然而,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
调用,但经过一些研究和大量谷歌搜索后,我仍在努力解决它。
您想await
duplicateSections 返回的所有承诺:
await Promise.all(sectionIDs.map(element =>
duplicateSection(trx, element.id, newQuestionnaireId)
));
这不仅确保在您 运行 最终查询之前复制所有部分,它还会链接被拒绝的承诺。
我有以下异步函数来复制名为 'Questionnaires' 的 postgres 数据库 table 中的记录:
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);
};
复制后,它将调用第二个异步函数来复制 table 中名为 '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);
};
These functions are designed with a hierarchy in mind:
duplicateQuestionnaire
callsduplicateSection
as a questionnaire contains sections. The latter function can be called without calling the former initially and does not call it as part of its actions.The return value of each function is used as a GraphQL return.
这两个函数对数据库都有预期的效果;他们工作。然而,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
调用,但经过一些研究和大量谷歌搜索后,我仍在努力解决它。
您想await
duplicateSections 返回的所有承诺:
await Promise.all(sectionIDs.map(element =>
duplicateSection(trx, element.id, newQuestionnaireId)
));
这不仅确保在您 运行 最终查询之前复制所有部分,它还会链接被拒绝的承诺。