2017-04-08 20 views
0

配列の各項目にいくつかの追加値を追加しようとしています。だから私はオブジェクトを持つ配列を持って、彼らは持っている:x、y、zフィールド。次に、http.get呼び出しの応答に基づいて配列の各オブジェクトに項目を追加したいとします。ForEachはメインアレイを更新しません

主な配列は次のとおりです。投稿

以下

を参照してくださいコード:post.profilePic = parsedBody.user.profilePic

router.get('/api/posts', function(req, res){ 

    postModel.find({}) 
     .limit(10) 
     .exec(function(err, posts) { 
      var options = { 
       host: 'localhost', 
       port: 3000, 
       path: '/user?id=12345678', 
       method: 'GET' 
      }; 
      if(posts){ 
       posts.forEach(function(post) { 

        var req = http.get(options, function(res) { 
         var bodyChunks = []; 
         res.on('data', function(chunk) { 
          bodyChunks.push(chunk); 
         }).on('end', function() { 
          var body = Buffer.concat(bodyChunks); 
          var parsedBody = JSON.parse(body); 
          post.fullname = parsedBody.user.fullname; 
          post.profilePic = parsedBody.user.profilePic; 
         }); 
        });  
       }); 
      res.json({ 
       posts  : posts 
      }); 
      } else { 
       res.send('Post does not exist'); 
      } 
     }); 
}); 

- profilePic変数がありますノードからres.json経由で応答があった場合、追加の値は返されません。

私はここで何が欠けていますか?私はこのアプローチを問題なしに常にAngularフロントエンドで使用しています。

ありがとうございました

+0

いくつかの変数 'var temp = post'に' post'を割り当ててください。その変数 'temp.fullname = parsedBody.user.fullname;'と 'post.profilePic = parsedBody.user.profilePic'に' fullname'と 'profilePic'を追加します。 'posts'の代わりに' temp'を返してください。 –

+0

コメントありがとうございます。このアプローチはうまくいくでしょうが、確かにネイティブな方法が正しいでしょうか?データの大部分がすでにそこにある配列にプッシュする必要があります。この場合、メモリに大きなオーバーヘッドが生じます(実際のデータは膨大です)。 –

答えて

2

でなければなりません

post.fullname = parsedBody.user.fullname; 
post.profilePic = parsedBody.user.profilePic; 

であることは、同期であるかのように、あなたは非同期コードを扱っています。 http.getは即座に完了せず、コードの継続をブロックしないため、要求が完了する前にres.jsonが呼び出されます。これを修正する方法はたくさんあります。私は好きなものを投稿します - Javascript Promises

// use map instead of forEach to transform your array 
// of posts into an array of promises 
var postPromises = posts.map(function(post) { 
    return new Promise(function(resolve) { 
    var req = http.get(options, function(res) { 
     var bodyChunks = []; 
     res.on('data', function(chunk) { 
      bodyChunks.push(chunk); 
     }).on('end', function() { 
      var body = Buffer.concat(bodyChunks); 
      var parsedBody = JSON.parse(body); 
      post.fullname = parsedBody.user.fullname; 
      post.profilePic = parsedBody.user.profilePic; 
      // resolve the promise with the updated post 
      resolve(post); 
     }); 
    }); 
    }); 
}); 

// once all requests complete, send the data 
Promise.all(postPromises).then(function(posts) { 
    res.json({ 
    posts: posts 
    }); 
}); 
+0

ああ、もう一度これらのものの一つ!私はいつも私がそれらに巻き込まれる方法が嫌い。ありがとう、ロブ。これは魅力のように私のために働いた! –

+0

素晴らしい...その本当に最高の... –

0

ノードはコールバックに従って動作します。 forEachループで完了していないコールバックがあり、ユーザーに応答しています。これが問題です。

解決策を提案できるコードを記述してください。あなたがやっている

router.get('/api/posts', function(req, res){ 

    postModel.find({}) 
     .limit(10) 
     .exec(function(err, posts) { 
      var options = { 
       host: 'localhost', 
       port: 3000, 
       path: '/user?id=12345678', 
       method: 'GET' 
      }; 
      if(posts){ 
       var EventEmitter = require('events'); 
       var HttpEvent = new EventEmitter(); 
       let counts = 0; 
       let length = posts.length; 

       posts.forEach(function(post) { 

        var req = http.get(options, function(res) { 
         var bodyChunks = []; 
         res.on('data', function(chunk) { 
          bodyChunks.push(chunk); 
         }).on('end', function() { 
          var body = Buffer.concat(bodyChunks); 
          var parsedBody = JSON.parse(body); 
          posts.fullname = parsedBody.user.fullname; 
          posts.profilePic = parsedBody.user.profilePic; 
          HttpEvent.emit('done'); 
         }); 
        });  
       }); 

       HttpEvent.on('done',()=>{ 
        counts += 1; 
        if(counts == length){ 
         res.json({ 
          posts  : posts 
         }); 
        } 
       }) 

      } else { 
       res.send('Post does not exist'); 
      } 
     }); 
}); 

つ以上間違ったことは、これは非常に共通の問題である

posts.fullname = parsedBody.user.fullname; 
posts.profilePic = parsedBody.user.profilePic; 
+0

コメントありがとうございます。私はちょうどそれを行ったが、それは動作しませんでした。返されるデータにはまだ値がありません。 ** post.fullname = parsedBody.user.fullname; **の場合も、ループの一部としてその名前が付けられます。私は** post **をforEachに渡します –

関連する問題