簡體   English   中英

如何在Node.js中正確處理異步函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM