3

我对 node.js、postgresql、promises 和事实上的 stackoverflow 比较陌生,所以如果事情听起来有点脱节,请提前道歉!

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

我尝试了以下方法,我正在添加一名学生并为该学生分配两名导师。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.... 

任何帮助将非常感激。提前谢谢你。

4

1 回答 1

3

根据我之前的评论:

该错误意味着您正在尝试访问t任务回调函数之外某处的任务分配的连接,即任务的回调已返回,连接已释放,然后您正在使用任务从其他地方分配的连接对象,这当然是无效的。

顺便说一句,我是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!
    });

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

于 2017-01-18T15:32:59.860 回答