Javascript 阵列中充满了未兑现的承诺?

Javascript 阵列中充满了未兑现的承诺?,javascript,arrays,node.js,Javascript,Arrays,Node.js,我很快就要完成这个函数的基础了,但是我被卡住了,还有一点要做,因为我缺乏承诺方面的知识,我正在学习它们是如何工作的等等。关于我的问题,我正在循环一些数据,这些数据存储在一个数组中,然后通过承诺链传递给另一个函数,但是,阵列中充满了未决承诺,我只需要将承诺中的实际数据放入阵列中,请参见下面的内容以了解发生了什么: var getGameData = function(matchIdArray) { var promise = new Promise(function(resolve,reject)

我很快就要完成这个函数的基础了,但是我被卡住了,还有一点要做,因为我缺乏承诺方面的知识,我正在学习它们是如何工作的等等。关于我的问题,我正在循环一些数据,这些数据存储在一个数组中,然后通过承诺链传递给另一个函数,但是,阵列中充满了未决承诺,我只需要将承诺中的实际数据放入阵列中,请参见下面的内容以了解发生了什么:

var getGameData = function(matchIdArray) {
var promise = new Promise(function(resolve,reject) {
  console.log('Start getGameData');
  s3.headObject({Bucket: 'lolsearchgames', Key: '347341'}, function(err, result) {
    console.log('Checking Bucket');
    if (err && err.code === 'NotFound') {
      console.log('Bucket data Not Found!')
      var gameData = new Array();
      for (var i = 0; i < matchIdArray.length; i++) {
        gameData.push(new Promise(function(res, rej) {
          lolapi.Match.get(matchIdArray[i], function (error, gamedata) {
            if (error) {
                rej(error);
            }
            if (gamedata) {
                console.log('Pushing new data to Array! ' + gamedata.matchId);
                res(gamedata);
            }
          })
        }));
      }
      if (gameData.length === 10) {
          console.log(gameData);
          resolve(gameData);
      }
    } else {
      console.log('Bucket data Found!');
    }
  })
});
return promise;
console.log('End getGameData');
};
var getGameData=function(匹配数组){
var承诺=新承诺(功能(解决、拒绝){
log('Start getGameData');
s3.headObject({Bucket:'lolsearchgames',Key:'347341'},函数(err,result){
console.log('检查Bucket');
if(err&&err.code==='NotFound'){
console.log('Bucket data Not Found!')
var gameData=新数组();
对于(变量i=0;i
使用Promise.all等待所有“游戏数据”,如下所示-还可以使用Array#map避免推送到数组

注意:但是,如果在任何lolapi.Match.get promise中有任何拒绝,那么promise.all将拒绝-这可能不是您想要的,我不能从您的代码示例中确定

var getGameData = function getGameData(matchIdArray) {
  var promise = new Promise(function (resolve, reject) {
    console.log('Start getGameData');
    s3.headObject({ Bucket: 'lolsearchgames', Key: '347341' }, function (err, result) {
      console.log('Checking Bucket');
      if (err && err.code === 'NotFound') {
        console.log('Bucket data Not Found!');
        Promise.all(matchIdArray.map(function(matchId) {
          return new Promise(function (res, rej) {
            lolapi.Match.get(matchId, function (error, gamedata) {
              if (error) {
                rej(error);
              }
              res(gamedata);
            });
          })
        }))
        .then(resolve)
        .catch(reject);
      } else {
        console.log('Bucket data Found!');
        reject('Bucket data Found!');
      }
    });
  });
  console.log('End getGameData');
  return promise.then(function (results) {  // see note below
    return results.filter(function (result) {
      return result;
    });
  });
};
备选方案-我认为“更整洁”的代码

如果您使用Bluebird promises,则它具有“promisify”节点回调样式函数的实用方法-在下面的代码中,
s3.headObjectAsync
s3.headObject
的promisified版本,而
lolapi.Match.getAsync
lolapi.Match.get
的promisified版本

您将看到,使用Bluebird promisify(以及ES2015+箭头符号,因为您使用的是node)使代码更加紧凑

var getGameData = function getGameData(matchIdArray) {
    return s3.headObjectAsync({
        Bucket: 'lolsearchgames',
        Key: '347341'
    })
    // do some gymnastics, because if there's no error, that should reject
    // but if the error is "NotFound" that should resolve
    .then(results => {
        throw {code: 'Bucket data Found!'};
    })
    .catch(err => {
        if (err && err.code === "NotFound") {
            return; // this is OK
        }
        throw err;
    })
    .then(() => Promise.all(matchIdArray.map(matchId => lolapi.Match.getAsync(matchId))))
    .then(results => results.filter(result => result)); // see note below
}
在ES5代码中,上面的代码仍然非常紧凑

var getGameData = function getGameData(matchIdArray) {
    return s3.headObjectAsync({
        Bucket: 'lolsearchgames',
        Key: '347341'
    }).then(function (results) {
        throw { code: 'Bucket data Found!' };
    }).catch(function (err) {
        if (err && err.code === "NotFound") {
            return; // this is OK
        }
        throw err;
    }).then(function () {
        return Promise.all(matchIdArray.map(function (matchId) {
            return lolapi.Match.getAsync(matchId);
        }));
    }).then(function (results) {  // see note below
        return results.filter(function (result) {
            return result;
        });
    });
};
请注意,在所有这些答案中,给出原始代码后,结果将与您期望的不完全相同。在您的原始代码中,如果
gamedata
是错误的,那么您只需忽略“Match.get”。。。然而,你不能用承诺——最后一个。然后在答案中过滤掉
getGameData


使用Promise.all等待所有“gameData”,如下所示-还可以使用Array#map避免推送到数组

注意:但是,如果在任何lolapi.Match.get promise中有任何拒绝,那么promise.all将拒绝-这可能不是您想要的,我不能从您的代码示例中确定

var getGameData = function getGameData(matchIdArray) {
  var promise = new Promise(function (resolve, reject) {
    console.log('Start getGameData');
    s3.headObject({ Bucket: 'lolsearchgames', Key: '347341' }, function (err, result) {
      console.log('Checking Bucket');
      if (err && err.code === 'NotFound') {
        console.log('Bucket data Not Found!');
        Promise.all(matchIdArray.map(function(matchId) {
          return new Promise(function (res, rej) {
            lolapi.Match.get(matchId, function (error, gamedata) {
              if (error) {
                rej(error);
              }
              res(gamedata);
            });
          })
        }))
        .then(resolve)
        .catch(reject);
      } else {
        console.log('Bucket data Found!');
        reject('Bucket data Found!');
      }
    });
  });
  console.log('End getGameData');
  return promise.then(function (results) {  // see note below
    return results.filter(function (result) {
      return result;
    });
  });
};
备选方案-我认为“更整洁”的代码

如果您使用Bluebird promises,则它具有“promisify”节点回调样式函数的实用方法-在下面的代码中,
s3.headObjectAsync
s3.headObject
的promisified版本,而
lolapi.Match.getAsync
lolapi.Match.get
的promisified版本

您将看到,使用Bluebird promisify(以及ES2015+箭头符号,因为您使用的是node)使代码更加紧凑

var getGameData = function getGameData(matchIdArray) {
    return s3.headObjectAsync({
        Bucket: 'lolsearchgames',
        Key: '347341'
    })
    // do some gymnastics, because if there's no error, that should reject
    // but if the error is "NotFound" that should resolve
    .then(results => {
        throw {code: 'Bucket data Found!'};
    })
    .catch(err => {
        if (err && err.code === "NotFound") {
            return; // this is OK
        }
        throw err;
    })
    .then(() => Promise.all(matchIdArray.map(matchId => lolapi.Match.getAsync(matchId))))
    .then(results => results.filter(result => result)); // see note below
}
在ES5代码中,上面的代码仍然非常紧凑

var getGameData = function getGameData(matchIdArray) {
    return s3.headObjectAsync({
        Bucket: 'lolsearchgames',
        Key: '347341'
    }).then(function (results) {
        throw { code: 'Bucket data Found!' };
    }).catch(function (err) {
        if (err && err.code === "NotFound") {
            return; // this is OK
        }
        throw err;
    }).then(function () {
        return Promise.all(matchIdArray.map(function (matchId) {
            return lolapi.Match.getAsync(matchId);
        }));
    }).then(function (results) {  // see note below
        return results.filter(function (result) {
            return result;
        });
    });
};
请注意,在所有这些答案中,给出原始代码后,结果将与您期望的不完全相同。在您的原始代码中,如果
gamedata
是错误的,那么您只需忽略“Match.get”。。。然而,你不能用承诺——最后一个。然后在答案中过滤掉
getGameData


Promise。承诺数组上的所有
返回一个承诺,当它们全部解析时,该承诺解析为结果数组。承诺数组上的所有返回一个承诺,当它们全部解析时,该承诺解析为结果数组避免承诺构造函数反模式@Bergi-是的,我本来想添加它,但是
s3.headObject
中的逻辑让我困惑,因为它如果没有错误,就会拒绝@Bergi-我添加了一个依赖于Bluebird promisify的版本-在使用具有节点样式回调的函数时,我看不到任何其他简单的方法来避免promise构造函数反模式-老实说,我不确定您的评论在这种情况下是否合理,因为,让我们面对它,Bluebird promisify(或promise/then's Denodesify)Promise构造函数对你有用吗?所以你不是在回避它,你是在把它链接到什么地方,使用Promise构造函数对
头对象
获取
进行Promission没有错,反模式只指使用其他承诺(尤其是
Promise.all
及其组成部分)在承诺构造函数回调中。您的第二个代码段非常好。@Bergi-第二个代码段与第一个代码段具有完全相同数量的承诺构造函数(两个),因此我猜短语
避免承诺构造函数反模式
并不是我所想的意思,即,避免在不需要的地方使用
新承诺
避免承诺构造函数反模式@Bergi-是的,我本来想添加它,但是
s3.headObject
中的逻辑让我困惑,因为它如果没有错误,就会拒绝@Bergi-我已经添加了一个依赖于Bluebird promisify的版本-在使用具有节点样式回调的函数时,我看不到任何其他简单的方法来避免promise构造函数反模式-老实说,我不确定您的评论在这种情况下是否合理,因为,让我们面对它,Bluebird promisify(或promise/then的denod)