2017-01-18 28 views
1

我对node.js,postgresql,promises和infact stackoverflow比较新,如果事情听起来有点不连贯,请提前道歉!在多个控制器之间的多个查询之间共享事务或任务对象pg-promise

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

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

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

+0

这个错误意味着你试图访问任务的回调函数以外的任务分配的连接't',即任务的回调已经返回,连接被释放,然后你正在使用连接对象来自其他地方的任务,这当然是无效的。 –

回答

2

按我先前的评论:

该错误意味着您试图访问由任务外任务的回调函数的地方分配的连接t,即任务的回调已经恢复,连接被释放,然后你从其他地方使用任务分配的连接对象,当然这是无效的。

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! 
    }); 

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

+1

谢谢。这确实发生在我身上,因为我之前管理的事务可以正常工作,但所有查询都在同一个存储库中。我可以让任务在不同的控制器和存储库中工作,但当前在控制器中启动任务,而不是第一个调用的存储库。 – Faz

+0

@Faz如果你按照[pg-promise-demo](https://github.com/vitaly-t/pg-promise-demo)中所示的可重用模式,那么你将不会有问题重复使用你的仓库方法,因为它们可以从根目录中获得,再加上所有的任务和事务。 –

相关问题