2017-01-18 20 views
1

私はnode.js、postgresql、約束事、そして事実上のstackoverflowを比較的新しくしています。pg-promiseの複数のコントローラ間で複数のクエリ間でトランザクションまたはタスクオブジェクトを共有する

現在、私は、さまざまなコントローラ間に広がる連鎖した約束の中で複数のクエリを実行しようとしています。同じトランザクションまたはタスク内ですべてのクエリを実行して、複数の接続を排除してデータベースとの接続を切断したいと考えています。

私は学生を追加して、その学生のために2人のメンターを割り当てています。 HTTP要求は生徒用コントローラにルーティングされ、生徒用のリポジトリを介して生徒を追加します。学生のリポジトリは学生リポジトリ

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

}) 
} 

メンター・グラフィックスコントローラ

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

    }) 

}); 

} 

どこタスクが開始され、メンターコントローラに、それが行くチェーンに沿って、それを転送コントローラに返される...

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.... 

すべてのヘルプははるかに高く評価されるだろう。よろしくお願いします。私の以前のコメントを1として

+0

このエラーは、タスクのコールバック関数の外側のタスクによって割り当てられた接続 't'にアクセスしようとしていることを意味します。つまり、タスクのコールバックが返され、接続が解放され、タスクは他の場所から、もちろん無効です。 –

答えて

2

というエラーがタスクのコールバックが戻ってきた。すなわち、接続が解放された、どこかのタスクのコールバック関数の外でタスクによって割り当てられた接続tにアクセスしようとしていること、タスクによって割り当てられた接続オブジェクトを他の場所から使用しています。これはもちろん無効です。

b.t.w.

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

あなたはこれが起こらないことを確認するために、実装を修正する必要があります。

以下はあなたのコードが効果的に簡略化した形で、やっものです)、私はpg-promiseの著者です。

+1

ありがとうございます。これは私が以前に管理していたトランザクションが機能するようになったときに発生しましたが、すべてのクエリは同じリポジトリに格納されていました。私はタスクを異なるコントローラとリポジトリ間で動作させることができますが、現在コントローラと呼ばれる最初のリポジトリとは対照的に、コントローラでタスクを開始しています。 – Faz

+0

@Faz [pg-promise-demo](https://github.com/vitaly-t/pg-promise-demo)に示すように再利用可能なパターンに従うと、リポジトリの再利用で問題は発生しませんメソッド、それらがルートから利用可能なので、すべてのタスクとトランザクション。 –

関連する問題