2017-10-10 12 views
0

コンテキスト

私は2つのmongodbモデル、アカウントと会話を持っています。 各アカウントには、すべての会話のうち、whoと会話のIDが含まれています。モンゴースのネストされた非同期クエリコールバック

Facebookのメッセンジャーに似たページを作成しようとしています(左側の会話リスト、右側のチャット)。


問題

コードは、チャットの非同期内部Promise <Pending>エラーでハングアップします。私は最高のコーダーではなく、私はそれが私に何を期待しているのか理解していません。それはネストされたクエリまたはそれのようなものを待つ必要があるように聞こえる?


コード

router.get('/chat/:id', function(req, res) { 
    if (req.user == undefined) { 
    return res.redirect('/'); 
    } 
    else { 
    async.parallel({ 
     conversations: function (err, users){ 
     Account.find({'_id': {$ne: req.user._id}}).exec(err, users) 
     }, 
     chat: function (err,talk){ 
      Account.find({'_id': req.user._id, 'conversations.with': req.params.id}).exec(function(err, talk){ 
       //if conversation ID doesn't exist, create. 
       if(!talk.length){ 
       console.log(err + " No convo with ParamsId exists: " + req.params.id); 
       var newConvo = new Conversation({ 
        owners  : [req.user._id, req.params.id], 
        created_at : Date.now() 
       }); 
       newConvo.save(function(err, convo){ 
        //push conversation ID to both users 
        async.parallel({ 
        modelAFind: function (A){ 
         Account.findByIdAndUpdate(req.user._id, {$push: {'conversations': {'with':req.params.id, 'conversation': convo._id}}}, {safe:true, upsert: true, new : true}).exec(A) 
        }, 
        modelBFind: function (B){ 
         Account.findByIdAndUpdate(req.params.id, {$push: {'conversations': {'with':req.user._id, 'conversation': convo._id}}}, {safe:true, upsert: true, new : true}).exec(B) 
        } 
        }), 
        Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(talk); 
       }); 
      } 
      else if (err){console.log(err)} 
      //else if conversation ID exists 
      else { 
       // CODE HANGS HERE!! 
       Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(talk); 
      } 
      }); 
     }, 
    }, 
    function(err, result,next){ 
     var ret = result.conversations; 
     console.log(result); 
     ret.dataB = result.chat; 
     res.render('chat', { 
     user: req.user, 
     users: ret, 
     profile : req.params.id, 
     title : req.params.id + 'とチャット', 
     conversationId: ret.dataB 
     }); 
    }); 
    } 
}); 

どのように成功した)(Conversation.findOneからデータを得ることができますか?

ありがとうございました!

答えて

0

私は、問題はここにあると信じて:

あなたは、あなたはまた、同様Account.findtalkの結果に名前を付け、talkとして、async.parallelが提供するコールバックに名前を付けます。このtalk変数はAccount.find以前の結果によって影が薄くされているので

Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(talk); 

しかし:

chat: function (err,talk){ 
     Account.find({'_id': req.user._id, 'conversations.with': req.params.id}).exec(function(err, talk){ 

は、その後私は後であなたがtalkという名前のコールバックを、渡すためにしてみてください参照してください。

したがってasync.parallelコールバックは決して呼び出されないので、決して終了しません。

これを修正するには、一般的な規則でasyncとnode.jsモジュールに従うことをお勧めします。callbackまたはcbと呼びましょう。これに

chat: function (err,cb){ 

、後でそれを渡します:

だからあなたは、この行を変更し

Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(cb); 

あなたはノード7.5.0以降を使用している場合、またはバベルのようなものを使用して喜んで、新しいawait/async Javascript機能を使用することをお勧めします。私は間違いを犯すことが難しく、理解しやすい、保守が容易、再書いたあなたのコードがそれにして、それは多くのクリーナーのようになります。

router.get('/chat/:id', async function(req, res) { 
    if (req.user == undefined) { 
    return res.redirect('/'); 
    } 

    // We haven't called await on this promise yet, so it will be running in 
    // parallel with the other stuff bellow 
    const conversationsPromise = Account.find({'_id': {$ne: req.user._id}}).exec(); 

    const talk = await Account.find({'_id': req.user._id, 'conversations.with': req.params.id}).exec(); 

    let conversation; 

    if(!talk.length){ 
    console.log(err + " No convo with ParamsId exists: " + req.params.id); 
    var newConvo = new Conversation({ 
     owners  : [req.user._id, req.params.id], 
     created_at : Date.now() 
    }); 

    // Await both promises in parallel 
    await Promise.all([ 
     Account.findByIdAndUpdate(req.user._id, {$push: {'conversations': {'with':req.params.id, 'conversation': convo._id}}}, {safe:true, upsert: true, new : true}).exec(), 
     Account.findByIdAndUpdate(req.params.id, {$push: {'conversations': {'with':req.user._id, 'conversation': convo._id}}}, {safe:true, upsert: true, new : true}).exec(), 
    ]); 

    conversation = await Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(); 
    } 
    else if (err){console.log(err)} 
    //else if conversation ID exists 
    else { 
    conversation = await Conversation.findOne({'owners': {"$all":[req.user._id, req.params.id]}}).populate('owners messages.from').exec(); 
    } 

    var ret = await conversationsPromise; 

    console.log({ 
    chat: conversation, 
    conversations: ret, 
    }); 
    ret.dataB = conversation; 
    res.render('chat', { 
    user: req.user, 
    users: ret, 
    profile : req.params.id, 
    title : req.params.id + 'とチャット', 
    conversationId: ret.dataB 
    }); 
}); 
+0

これは今たくさんきれいで、あなたの説明が明らかになったあなたに感謝します – y4my4m

関連する問題