Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/43.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从forEach推送数组并传递到res_Javascript_Callback_Sails.js - Fatal编程技术网

Javascript 从forEach推送数组并传递到res

Javascript 从forEach推送数组并传递到res,javascript,callback,sails.js,Javascript,Callback,Sails.js,我对javascript和sails都是新手。我对javascript的回调有点困惑。现在我的控制器有以下方法: test: function(req, res) { var arr = [], someId = [15,16,7]; someId.forEach(function(val, idx) { var temp = {}; User.find({userId: val}).exec(function(err, usr) { Profile.find

我对javascript和sails都是新手。我对javascript的回调有点困惑。现在我的控制器有以下方法:

test: function(req, res) {
  var arr = [], someId = [15,16,7];
  someId.forEach(function(val, idx) {
    var temp = {};
    User.find({userId: val}).exec(function(err, usr) {
      Profile.find({profileId: usr.profId}).exec(function(err, prof) {
        temp.name = prof.fullName();
        temp.email = usr.email;
        ...
        arr.push(temp);
        res.json(arr);
      })
    })
  })
}
一切都进展顺利,但json响应只发送第一个值,而不是最后一个值,因此我假设res.json在回调执行期间只传递第一个
arr.push
。如何以及在何处调用
res.json
,使其仅在回调完成时执行。谢谢

test: function(req, res) {
  var arr = [], someId = [15,16,7];
  someId.forEach(function(val, idx) {
    var temp = {};
    User.find({userId: val}).exec(function(err, usr) {
      Profile.find({profileId: usr.profId}).exec(function(err, prof) {
        temp.name = prof.fullName();
        temp.email = usr.email;
        ...
        arr.push(temp);
      })
    })
  })
  res.json(arr);
}

你没有到达循环的终点。在完成第一项后,您已经传递了“ARR”的值

您必须等待所有回调完成。一个简单的方法是:每次运行
Profile.find
回调时,通过检查
arr
的长度来检查这是否是最后一个回调

someId.forEach(function(val, idx) {
    User.find({userId: val}).exec(function(err, usr) {
      Profile.find({profileId: usr.profId}).exec(function(err, prof) {
        var temp = {};
        temp.name = prof.fullName();
        temp.email = usr.email;
        ...
        arr.push(temp);

         // if arr is now full, send it; otherwise, wait for more
        if(arr.length == someId.length) { res.json(arr); }
      })
    })
})
但是,在查询
用户之前,您不知道“finished”数组有多长。这里的解决方案是先查询所有用户,然后再查询配置文件:

var usersProcessedCount = 0, matchedUsers = [];
someId.forEach(function(val, idx) {
    User.find({userId: val, status: 1}).exec(function(err, usr) {
      if(usr != null) { matchedUsers.push(usr); }
      if(++usersProcessedCount == someId.length) { fetchProfiles(); }
    })
})

function fetchProfiles() {
    matchedUsers.forEach(val, idx) {
      Profile.find({profileId: val.profId}).exec(function(err, prof) {
        var temp = {};
        temp.name = prof.fullName();
        temp.email = val.email;
        ...
        arr.push(temp);

         // if arr is now full, send it; otherwise, wait for more
        if(arr.length == matchedUsers.length) { res.json(arr); }
      })
    });
}

在这里,我们将满足条件的所有用户存储在一个数组中,然后,当我们处理完所有候选ID后,我们调用
fetchProfiles
,它在匹配的用户列表上循环。

您可以使用Waterline内置的“in”-查询语法简化查询:如果您将条件值设置为数组,它将搜索该字段的值与数组中的值匹配的所有记录。因此:

// Find all users whose ID is in the someId array
User.find({userId: someId}).exec(function(err, users) {

    if (err) {return res.serverError(err);

    // Get the profile IDs of those users using Lodash "pluck"
    var profileIds = _.pluck(users, 'profId');

    // Find all Profile records with those IDs
    Profile.find({profileId: profileIds}).exec(function(err, profiles) {

        if (err) {return res.serverError(err);

        // Use Array.map to transform the profiles array data
        var results = profiles.map(function(profile) {
            // Use Lodash to get the user with this profile ID
            var user = _.find(users, {profId: profile.profileId});
            return {name: profile.fullName(), email: user.email};
        });
        return res.json(results);

    });


});
请注意,默认情况下,
(Lodash)由Sails全球化,因此您可以在任何控制器、模型或服务中使用它

另一种方法是使用(也被Sails全球化)以更线性的方式重新组织代码,而不是使用嵌套回调

如果您使用的是帆V0.10.x,您也可以考虑使用直接关联用户和配置文件记录;然后你就可以做:

User.find({userId: someId}).populate('profile').exec(...);

获取所需的一切。

我已经尝试过这个方法,效果很好,但这里的问题是,如果在查询用户时设置一些约束会怎么样。例如,
User.find({userId:val})。where({'status':1})
usr长度与arr的长度不匹配。是否有其他解决方法?@mateeow编辑以解决您对筛选的担忧:构建一个筛选UER数组,然后根据该筛选列表执行配置文件的提取(并使用该列表的长度来确定完成的时间)。我认为这不起作用,因为usersProcessedCount只会增加到usr的长度,并且不是所有用户都具有状态1,如果(++usersProcessedCount==someId.length,则
将不会被删除true@mateeyow也许我误解了Sails处理空结果的方式。我假设没有找到匹配的请求(即记录的状态不是1)将使用
usr
null
值运行回调;因此,
usetsProcessedCount
将在匹配和非匹配查询上递增。您是否建议对于非匹配记录,回调根本不会运行?这似乎是错误的,因为您无法区分无结果请求和非常慢的查询请求。模型的
exec
方法是异步的,因此此代码在任何回调运行之前发送
arr
。您的代码启动所有请求,但它不会等待
exec
回调运行;因此,它在填充任何数据之前发送回
arr