[英]How properly handle async functions in 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
}));
});
});
當調用此代碼時,將在每個循環中發出數組,並在每個循環中再添加一個元素,但這對我不利。 當數組完全填充時,我想調用一次emit事件。
解決這類問題的首選方法是使用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};
}));
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.