如何正确处理nodejs中的异步函数

时间:2015-05-13 14:35:00

标签: javascript node.js sequelize.js

我是nodejs的新手,我不能正确理解异步功能的工作原理。我今天读了很多,但我无法解决我的问题。

我使用Sequelize.js作为ORM,我的问题是当我将查询嵌入到另一个查询的回调中时,我不能强制它仅在两个查询结束时继续。

这是我目前的代码:

io.on('connection', function (socket) {
  socket.on('join', function (data) {
    clients[clients.length] = new Client("Client " + clients.length, data.channel);
    console.log('Client connected Channel: ' + clients[clients.length-1].channel);
    var array = []
    DB.Matches.findAll({attributes: ['matchId', 'teamAId', 'teamBId']}).then(function (result) {
      for (var i = result.length - 1; i >= 0; i--) {
        DB.Teams.findAll({where: { team_id: [result[i].teamAId,result[i].teamBId]}}).then(function (teams) {
          array.push({ id: 0, name: teams[0].clubName + ' - ' + teams[1].clubName});         
        }).then(function () {
          // Now my emit event is here but I dont want to run every time the  loop run
          console.log(array);
          socket.emit('matches', array); 
        });
      }
    }.then(function () {
      // I tried to put it here, but then I got an empty array, because the queries haven't finshed yet 
    }));
  });
});

当调用此代码时,数组将在每个循环中发出,每个循环中都有一个元素,但这对我不利。我想在数组完全填充时调用一次emit事件。

1 个答案:

答案 0 :(得分:5)

解决此类问题的首选方法是使用Promise.all

return { id: result[i].matchId, name: teams[0].clubName + ' - ' + teams[1].clubName};

修改

如果我理解你,你想写 for(var i = result.length - 1; i >= 0; i--) { (function(i) { promises.push( DB.Teams.findAll({where: { team_id: [result[i].teamAId,result[i].teamBId]}}).then(function (teams) { return { id: result[i].matchId, name: teams[0].clubName + ' - ' + teams[1].clubName}; })); })(i); }

但这并不奏效。这行代码将在未来的某个时刻执行, 即,在for循环结束后,到那时i为-1。 为了使它工作,你需要为循环的每次迭代提供一个新变量。 你可以这样做,例如通过将代码包装在另一个函数中来完成这个

result.forEach(function(match) {
  promises.push(
    DB.Teams.findAll({where: { team_id: [match.teamAId,match.teamBId]}}).then(function (teams) {
       return { id: match.matchId, name: teams[0].clubName + ' - ' + teams[1].clubName};
    }));
});

这样你就可以在每次迭代中使用不同的i变量(存储在内存中的不同位置)。 但在这种情况下,最好的方法是使用forEach。唯一的区别是循环会 迭代遍历数组,而不是像for循环那样向后遍历。

Invoke-RestMethod