2017-04-08 70 views
0

我想添加一些額外的值到數組中的每個項目。所以我有一個包含對象的數組,它們有:x,y和z字段。然後我想根據http.get調用的響應將其他項添加到數組中的每個對象。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){ 
       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'); 
      } 
     }); 
}); 

post.profilePic = parsedBody.user.profilePic的時間 - profilePic變量是有但是當我通過res.json得到來自節點的響應時,附加值不是。

我在這裏錯過了什麼?我始終在Angular前端使用這種方法,而沒有任何問題。

謝謝

+0

嘗試一件事:將'post'分配給某個變量'var temp = post'。然後將'fullname'和'profilePic'添加到該變量'temp.fullname = parsedBody.user.fullname;'和'post.profilePic = parsedBody.user.profilePic'。現在返回'temp'而不是'posts'。 –

+0

感謝您的評論。這種方法可行,但肯定有一個更原始的方式是正確的?我將不得不推入數組,其中大部分數據已經存在,這會導致內存的巨大開銷(真實數據很大)。 –

回答

2

這是一個令人難以置信的常見的問題,就好像它是同步你是治療異步代碼。 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'); 
      } 
     }); 
}); 

還有一個你正在做錯誤的事情是

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

應該

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

感謝您的評論。我只是放棄了它,但它沒有奏效。返回的數據仍然沒有值。也爲** post.fullname = parsedBody.user.fullname; ** - 它以這種方式命名,因爲它是循環的一部分。我通過**發佈**在forEach –