ForEach不更新主阵列

时间:2017-04-08 05:58:45

标签: javascript node.js

我正在尝试为数组的每个项添加一些额外的值。所以我有一个包含对象的数组,它们有:x,y和z字段。然后,我想根据http.get调用的响应为数组中的每个对象添加其他项。

主要数据是:帖子

见下面的代码:

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前端没有问题。

由于

2 个答案:

答案 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
  });
});

答案 1 :(得分: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;