2017-03-05 37 views
0

從下面的代碼,我試圖解決後ONLY遊戲對象已經從API循環填充它的數據如果是有道理的承諾,但它一直顯示空:只有在變量填滿後才解析承諾?

{ 
    info: summoner, 
    matchIds: {        << used for loop below 
     0: matchIds['matches'][0].matchId, 
     1: matchIds['matches'][1].matchId, 
     2: matchIds['matches'][2].matchId, 
     3: matchIds['matches'][3].matchId, 
     4: matchIds['matches'][4].matchId, 
     5: matchIds['matches'][5].matchId, 
     6: matchIds['matches'][6].matchId, 
     7: matchIds['matches'][7].matchId, 
     8: matchIds['matches'][8].matchId, 
     9: matchIds['matches'][9].matchId 
    } 
} 

var getMatches = function(summoner) { 
    var promise = new Promise(function(resolve, reject){ 
     var opt = {}; 
     var games = {};       << object needs to be filled 
     for (var val in Object.keys(summoner['matchIds'])) { 
      var match = summoner['matchIds'][val]; 
      opt.id = match; 
      api.getMatchById(opt, function(err, game) { 
       games[x] = game; 
      }) 
     } 
     console.log(games); 
     resolve({games}); 
    }); 
    return promise; 
}; 

回答

1

你的代碼是假設api.getMatchById()是同步的,但它可能不是,因此for循環在你的任何api.getMatchById()調用完成之前完成,因此當你解決時遊戲總是空的。您將不得不跟蹤所有api.getMatchById()調用何時完成,並且只有在發生時才能解決。

對此進行編碼的最佳方法是對api.getMatchById()進行promisify,然後使用Promise.all()來跟蹤它們何時全部完成。如果你不打算這樣做,那麼你可以創建一個手動計數器:

var getMatches = function(summoner) { 
    return new Promise(function(resolve, reject){ 
     var cntr = 0; 
     var opt = {}; 
     var games = {}; 
     var keys = Object.keys(summoner['matchIds']); 
     keys.forEach(function(key) { 
      var match = summoner['matchIds'][key]; 
      opt.id = match; 
      api.getMatchById(opt, function(err, game) { 
       // need some error handling here 
       games[x] = game; 
       ++cntr; 
       // when all api calls are done, resolve 
       if (cntr === keys.length) { 
        resolve({games}); 
       } 
      }) 
     }); 
    }); 
}; 

另外,請千萬不要使用/在遍歷數組的項目,因爲它可以容易出現問題。在ES6中,您可以使用for/of。我在這裏使用.forEach()

+0

@Evant - 這是否回答了您的問題? – jfriend00

0

你好可能的解決方案,如果使用,而不是純粹的承諾,但bluebird

const Promise = require('bluebird'); 
const promise = new Promise(function (resolve, reject) { 
    const propsPromise = {}; 
    Object.keys(summoner['matchIds']).forEach(val => { 
    const match = summoner['matchIds'][val]; 
    propsPromise[match] = new Promise((resolve, reject) => { 
     api.getMatchById(opt, (err, game) => { 
      if (err) { 
       return reject(err); 
      } 
      resolve(game); 
     }); 
    });}); 
    return Promise.props(propsPromise); 
}); 

你出去承諾將盡快解決的對象將與內容得到解決。

鏈接到文檔 - Promise.props

+1

你錯過了'返回Promise.props(propsPromise);' –

+0

@JaromandaX thnx,修正了。 – Selvatico