2017-11-10 11 views
0

下記のコードは、蛇行ORMを使用してDBクエリを作成し、レスポンスを送信しています。しかし、実行フローが奇妙です。マップ関数のコードは、マップ関数が実行を終了する前に実行されています。 「私は地図の外にあります」の前にコンソールに「私は地図の内側にあります」と表示されています。私はそれがプロミスまたは非同期/待つことを使用してこれを解決することができると思う。私は以下のPromise.all()を使ってみましたが、動作しません。応答は常に空の配列です。このような問題を解決する方法の例を挙げることができれば、感謝しています。array.map()内のセイル・ウォーターラインORMクエリー

allMembers: (req, res) => { 
    const projectId = req.params.id; 

    ProjectMembers.find({projectId: projectId}).exec((err, members) => { 
     if(err) res.serverError("bad request!"); 

     if(members.length === 0) res.notFound({message: "No members are found for this project!"}); 

     let membersInfo = []; 
     let promise = Promise.all(members.map(m => { 
      User.findOne({id: m.userId}).exec((err, user) => { 
       if(err) membersInfo.push({name: null, userId: null, email:null,rate:null, error: 'Internal error!'}) 
       else if(!user) membersInfo.push({name: null, userId: null, email:null,rate:null, error: 'No user found'}) 
       else membersInfo.push({name: user.name, userId: user.id, rate: m.rate, error: null}) 
       console.log("i am inside of map"); 
      }) 
     })); 

    console.log("I am outsie of map") 
    promise.then((resolve) => {return res.ok({members: membersInfo})}); 
} 

答えて

2

私は「.mapでクエリを使用していない」あなたを伝えることを約あったが、ご覧の上、私はあなたのコードが動作に非常に近いと思います。 Promise.allの議論は、約束の配列でなければならない。それぞれのUser.findOneは確かに約束です - 厄介な問題は、一度.execを使用すると、もはや約束を返さないということです。

私は答えが.map内の代わりに右の.then内のあなたの処理を行うことであると思う:

ProjectMembers.find({projectId: projectId}).exec((err, members) => { 
    if(err) return res.serverError("bad request!"); 

    if(members.length === 0) return res.notFound({message: "No members are found for this project!"}); 

    let promise = Promise.all(members.map(m => User.findOne({id: m.userId}))); 

    promise.then((values) => { 
     // values is the array of user objects returned from the array of queries 
     let membersInfo = values.map((user) => { 
      if (!user) { 
       return {name: null, userId: null, email:null,rate:null, error: 'No user found'}; 
      } else { 
       return {name: user.name, userId: user.id, rate: m.rate, error: null}; 
      } 
     }); 
     return res.ok({members: membersInfo}); 
    }, (err) => { 
     return res.serverError("Error finding users"); 
    }); 

約束だけ持つ単一の失敗のコールバック、あなたは個別キャッチする能力を失うようにクエリのエラーを処理します(ただし、まだ見つからない結果を個別に処理することはできます)。

+0

良い。選択したデータベースに応じて、個々のfondOnesではなく、ユーザーIDにOR条件を持つ1つの大きな 'User.find'を実行できます。 –

+0

@ManuelReilそれは私が取っていたアプローチであり、水線は間違いなく基礎となるデータベースでそれを行うことができます。私はちょうど合理的で作業に近いOPのロジックに近づけようとしていました。 – arbuthnott

関連する問題