2015-05-13 88 views
1

我是新来的NodeJS,我不正确地理解如何运作异步工作异步功能。我今天读了很多关于他们的文章,但我无法解决我的问题。如何妥善处理的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 
    })); 
    }); 
}); 

当该代码被调用时,阵列将在每一个循环在一个更多元的每一个回路可以emited,但这不是为我好。当数组完全填充时,我想调用emit事件一次。

+0

[标签:sequelize.js]不具有'DB.Matches.findAll({属性:[ 'matchId', 'teamAId', 'teamBId']})'方法。请阅读文档[here](http://docs.sequelizejs.com)。 –

+0

DB.Matches和DB.Teams是必需的()模式等: 'module.exports =函数(sequelize,Sequelize){ 变种模块= {}; 模块= sequelize.define( 'tbl_team',{ blablabla });返回模块; };' – NoNameProvided

回答

5

解决这种东西的最佳方式是使用Promise.all

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); 
    DB.Matches.findAll({attributes: ['matchId', 'teamAId', 'teamBId']}).then(function (result) { 
     var promises = []; 
     for (var i = result.length - 1; i >= 0; i--) { 
     promises.push(
      DB.Teams.findAll({where: { team_id: [result[i].teamAId,result[i].teamBId]}}).then(function (teams) { 
      return { id: 0, name: teams[0].clubName + ' - ' + teams[1].clubName};   
      })); 
     } 
     Promise.all(promises).then(function(array) { 
      console.log(array); 
      socket.emit('matches', array); 
     }); 
    }); 
    }); 
}); 

编辑:

如果我理解正确,你想写 return { id: result[i].matchId, name: teams[0].clubName + ' - ' + teams[1].clubName};

但这是行不通的。该行代码在将来某个时间点执行,即 ,即在for循环结束之后,并且此时i为-1。 为了使它工作,你需要一个新的变量为循环的每个迭代。 你可以这样做,例如通过包装中的代码的另一个功能是这样

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

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

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}; 
    })); 
}); 
+0

谢谢!这是我想念的地方:)你是什么意思发送到数据通道,而不是套接字? – NoNameProvided

+0

忘记我对数据通道的看法。我不熟悉socket.io。 – SpiderPig

+0

还有一个问题,如果我想用外部查询(result [i] .matchId)中的walue设置id,而不是如何做到这一点? – NoNameProvided