2015-05-13 133 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