在 pg-promise 中跨多个控制器的多个查询之间共享事务或任务对象

sharing a transaction or task object between multiple queries across multiple controllers in pg-promise

我对 node.js、postgresql、promises 和事实上的 Whosebug 比较陌生,所以如果听起来有点不连贯,请提前致歉!

我目前正在尝试 运行 跨多个控制器的链式承诺中的多个查询。我想 运行 同一事务或任务中的所有查询,以消除与数据库的多次连接和断开连接。

我尝试了以下添加学生并为该学生分配两名导师的方法。 HTTP 请求被路由到学生控制器,学生控制器通过学生存储库添加学生。学生存储库是任务开始并返回到控制器的地方,控制器将其转发给导师控制器并沿着链进行......

@ HttpPost("/api/students/create")
addStudent( @ Req()request) {

var studentid;
var mentorids= [];
//Add the student
return this.studentRepository.addStudent(request.body.student)
.then(newStudentId => {
    studentid = newStudentId;

    //Add the mentors, passing the transaction object received back from
      studentRepository

    return this.mentorController.addMentor(request.body.schoolid, request.body.mentors, newStudentId.transaction)
    .then(result => {
        var data = [];
        console.log(result);
        for (var role in result) {
            data.push({
                mentorid: result[role].roleid,
                studentid: studentid
            });
        }
        //Assigns the student to mentors in the link table
        return this.studentRepository.assignMentor(data)
        .then(result => {
            return result;
        })

    })

});

}

学生资料库

addStudent(student): any {
return this.collection.task(t => {
    return this.collection.one(this.sql.addStudent, student)
    .then(studentid => {
        return {
            studentid: studentid.studentid,
            transaction: t
        }
    });

})
}

导师控制器

addMentor(institutionid: number, mentors, t): any {

var promises = [];
var mentorIds = [];
for (var role in mentors) {
    promises.push(this.roleController.registerRole(institutionid,mentors[role].role,t));
}
return t.batch(promises)
.then(result => {
    return Promise.resolve(result);
})

}

角色控制器

@ HttpPost("/api/roles/register")
registerRole(institutionid,  @ Req()request, t ? ) : any {
console.log(request);
return this.roleRepository.checkRoleEnrollment(institutionid, request.email, request.roletype, t)
.then(result => {
    return this.roleRepository.addRoleEnrollment(institutionid, request, t)
    .then(data => {
        return this.roleRepository.updateRoleEnrollment(data.roleenrollmentid, data.roleid)
        .then(d => {
            return data;
        })

    })
})
.catch (error => {
    return Promise.reject(error);
});
}

当我在角色控制器中调用 checkEnrollment 时出现以下错误:

"name": "Error",
"message": "Unexpected call outside of task.",
"stack": "Error: Unexpected call outside of task. at Task.query   
(\api\node_modules\pg-promise\lib\task.js:118:19) 
at Task.obj.oneOrNone (\api\node_modules\pg-promise\lib\database.js:491:31)         
at RoleRepository.checkRoleEnrollment.... 

如有任何帮助,我们将不胜感激。提前致谢。

根据我之前的评论:

That error means you are trying to access connection t allocated by a task somewhere outside of the task's callback function, i.e. the task's callback has returned, the connection was released, and then you are using the connection object allocated by the task from somewhere else, which is, of course, invalid.

b.t.w。我是 pg-promise 的作者 ;)

以下是您的代码有效执行的简化形式:

var cnReference;

db.task(t => {
    cnReference = t;

    // can only use `t` connection while executing the callback
})
    .then(data => {
        // we are now outside of the task;
        // the task's connection has been closed already,
        // and we can do nothing with it anymore!
        return cnReference.query('SELECT...');
    })
    .catch(error => {
        // ERROR: Unexpected call outside of task.

        // We cannot use a task connection object outside of the task's callback!
    });

您需要更正实施以确保不会发生这种情况。