2017-01-18 31 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)中所示的可重用模式,那麼你將不會有問題重複使用你的倉庫方法,因爲它們可以從根目錄中獲得,再加上所有的任務和事務。 –

相關問題