Arrays 通过for循环在nodejs中构造数组

Arrays 通过for循环在nodejs中构造数组,arrays,node.js,asynchronous,sails.js,Arrays,Node.js,Asynchronous,Sails.js,我正在nodejs(6.9.1)上运行sails(0.11.0)。我试图通过填充for循环来构造一个数组。我会将这个完整的数组发送给客户端。例如,我已经尝试了这里的人在堆栈溢出方面建议的各种方法 讨论表明: for (var i = yearStart; i < yearEnd+1; i++) { arr.push(i); } 类似地,我尝试了许多方法,但遇到了相同的问题,即在循环期间,数组被填充,但一旦循环完成,由于异步过程,数组将变为空,因此我无法发送响应。为了解决这个问题,

我正在nodejs(6.9.1)上运行sails(0.11.0)。我试图通过填充for循环来构造一个数组。我会将这个完整的数组发送给客户端。例如,我已经尝试了这里的人在堆栈溢出方面建议的各种方法

讨论表明:

for (var i = yearStart; i < yearEnd+1; i++) {
    arr.push(i);
}
类似地,我尝试了许多方法,但遇到了相同的问题,即在循环期间,数组被填充,但一旦循环完成,由于异步过程,数组将变为空,因此我无法发送响应。为了解决这个问题,我尝试检查循环体内部的索引,并通过

var userArray = [];
_.each(users, function(user, index){
  MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){
    if(err){
      return res.json({"status":"some_error"});
    }else{
      userID = user.id
      userImageID = userImage[0][0].id;
      var userInfo = {
        userID: userID,
        userImageID: userImageID
      }
      userArray.push(userInfo)
      if(index == users.length - 1){
          res.json({selectedUsers: userArray});
      }
    }
  });
});
我正在启动一个空的userArray,然后遍历users对象,其中对象的每个元素都以nameuser索引为特征。通过MySQL查询,我获取userImage对象,并在每次迭代中创建一个名为userInfo的对象,该对象由userIDuserImageID组成。我正在将此对象推送到用户数组中。在for循环的每次迭代(
.each
)之后,我检查是否达到了最后一个索引。一旦到达最后一个索引,在循环体完成之前,最终数组将作为响应发送

这里我也有一个问题,数组体并不总是完全填充。原因是由于异步过程,索引不总是遵循顺序0,1,2,3,4,。。。。它可以从任何数字开始,在下一次迭代中可以跳转到任何索引,例如,第一个开始的索引是4,第二个是0,第三个是2,依此类推。每次运行for循环时,这个顺序都会不同。对于用户来说,这似乎是一个完全随机的过程。因此,如果users.length为8,并且在第三次迭代时当前索引随机为7,则将满足条件
index==users.length-1
,并且仅使用由3个元素而不是8个元素组成的数组发送响应


有人能给我建议一种更好、更健壮的方法,通过nodejs中的for循环填充一个数组,并发送该数组作为响应,以便所有项都以其原始顺序包含在数组中吗

在使用node js时,最好使用任何类似于或的库来处理异步请求。 您的循环未按预期工作的原因是,正如您所指出的,由于异步请求需要时间来解析
每个循环都没有等待

使用
蓝鸟
,可以使用以下文档中解释的方法完成:

给定一个Iterable(数组是Iterable)或一个Iterable的承诺, 产生承诺(或承诺和价值的混合),迭代 将Iterable中的所有值合并到一个数组中,并将该数组映射到 另一个是使用给定的映射器函数

将等待映射器函数返回的承诺,并且 返回的承诺只有在所有映射的承诺完成后才能实现 也实现了。如果数组中的任何承诺被拒绝,或 映射器函数返回的承诺被拒绝,返回 承诺也被拒绝了

因此,使用
Promise.map
可以如下更新代码:

var Promise = require("bluebird");     

return Promise.map(users, function(user, index){
  return MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){
    if(err){
      return Promise.reject({"status":"some_error"});
    }else{
      userID = user.id
      userImageID = userImage[0][0].id;
      var userInfo = {
        userID: userID,
        userImageID: userImageID
      }
      return userInfo;
    }
  });
})
.then(function (usersArray){
  res.json({selectedUsers: usersArray});
})
.catch(function (err){
  res.json(err);
});

您可以使用以下命令同步执行带有回调函数的循环:


谢谢,我将尝试promise库。但是我得到的响应数组是
[null,null,null,null,null,null]
应该可以工作,也许您得到的响应是null。在成功回调中返回
userInfo
之前,您是否可以放置一个日志并检查一次。是的,此空数组来自日志本身。您是否在查询后检查了
userImage
的值?它将不遵循顺序,我想您在map上也会遇到同样的问题。看看lodash和bluebird中的reduce,我知道在后者中它将保证顺序,我认为它与lodash相同,但可能是错误的。再仔细想想,在异步库中,我经常使用eachSeries,这也保证了顺序,可能是您现有代码的解决方案。
var Promise = require("bluebird");     

return Promise.map(users, function(user, index){
  return MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){
    if(err){
      return Promise.reject({"status":"some_error"});
    }else{
      userID = user.id
      userImageID = userImage[0][0].id;
      var userInfo = {
        userID: userID,
        userImageID: userImageID
      }
      return userInfo;
    }
  });
})
.then(function (usersArray){
  res.json({selectedUsers: usersArray});
})
.catch(function (err){
  res.json(err);
});
var SynJS = require('synjs');
var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'tracker',
  password : 'tracker123',
  database : 'tracker'
});


function myFunction1(modules,connection,users) {
    var ret=[];
    for(var i=0; i<users.length; i++) {
        connection.query("SELECT CONCAT('some image of user #',?) AS userImage", [users[i]], function(err, rows, fields) {
              if (err) throw err;

              ret.push({
                  id: users[i],
                  image:    rows[0].userImage
              });
              modules.SynJS.resume(_synjsContext); // <-- indicate that callback is finished
        });
        SynJS.wait(); // <-- wait for callback to finish
    }
    return ret;
};

var modules = {
        SynJS:  SynJS,
        mysql:  mysql,
};

var users = [1,5,7,9,20,21];

SynJS.run(myFunction1,null,modules,connection,users,function (ret) {
    console.log('done. result is:');
    console.log(ret);
});
done. result is:
[ { id: 1, image: 'some image of user #1' },
  { id: 5, image: 'some image of user #5' },
  { id: 7, image: 'some image of user #7' },
  { id: 9, image: 'some image of user #9' },
  { id: 20, image: 'some image of user #20' },
  { id: 21, image: 'some image of user #21' } ]