2017-04-08 1 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'를 할당하십시오. 그런 다음'fullname'과'profilePic'을 그 변수'temp.fullname = parsedBody.user.fullname;'과'post.profilePic = parsedBody.user.profilePic'에 추가하십시오. 이제'posts' 대신에'temp'를 반환하십시오. –

+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; **에 대해서 - 루프의 일부로 이름 붙여집니다. 나는 패스 ** post **에 대해 –

관련 문제