使用 AWS-SDK 为节点和蓝鸟从承诺中返回的数据

Data returned from promises with AWS-SDK for node and bluebird

我正在尝试为 AWS 中的每个区域获取所有已注册的弹性 IP。我目前正在处理的代码如下:

logger.info('About to fetch Regions');
ec2.describeRegionsPromised({}).then(function (data) {
  var addressesPromises = [];

  logger.info('Fetched Regions');
  logger.info(data);

  _.forEach(data.Regions, function (region) {
    var ec2Addresses = _.create(ec2, {region: region.RegionName});

    addressesPromises.push(ec2Addresses.describeAddressesPromised());
  });

  logger.info('About to fetch addresses per region');

  return Promise.all(addressesPromises);
}).then(function (data) {
  logger.info('Fetched addresses per region');
  logger.debug(data);
}).catch(function (err) {
  logger.error('There was an error when fetching regions and addresses');
  logger.error(err);
});

这工作正常,但我的问题是我正在查看第二个 .then promised-callback 函数 data 参数,它的数据是一个与 相同的数组第一次请求返回的区域长度.

我知道我只在一个区域使用了 1 个弹性 IP。对于所有其他地区,我没有任何关联。

返回的Regions如下(其实是格式化的JSON):

Regions=[RegionName=eu-west-1, Endpoint=ec2.eu-west-1.amazonaws.com, RegionName=ap-southeast-1, Endpoint=ec2.ap-southeast-1.amazonaws.com, RegionName=ap-southeast-2, Endpoint=ec2.ap-southeast-2.amazonaws.com, RegionName=eu-central-1, Endpoint=ec2.eu-central-1.amazonaws.com, RegionName=ap-northeast-1, Endpoint=ec2.ap-northeast-1.amazonaws.com, RegionName=us-east-1, Endpoint=ec2.us-east-1.amazonaws.com, RegionName=sa-east-1, Endpoint=ec2.sa-east-1.amazonaws.com, RegionName=us-west-1, Endpoint=ec2.us-west-1.amazonaws.com, RegionName=us-west-2, Endpoint=ec2.us-west-2.amazonaws.com]

在 JSON 中将是:

{ Regions: [] } //and so on

返回的弹性IP如下:

[ { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] },
  { Addresses: [ [PublicIp=XX.XX.XXX.XXX, AllocationId=eipalloc-XXXXXXXX, Domain=vpc] ] } ]

在响应中,我有一个对象数组,其中每个区域请求的对象键值都相同,这是错误的。

我希望在第二个响应中每个区域的值分辨率,将其余部分设置为 null、undefined 或类似的。

总结一下。我不明白为什么解析一组承诺的值(使用 .all)会在每个点得到一组相同的值——这不是预期的结果。

这是怎么回事?提前致谢!

我发现了问题。 正如 @Roamer-1888 指出的 ec2Addresses 对象的创建不正确。相反,我应该使用 EC2 对象的 AWS SDK 构造函数创建一个新实例。然而,问题的关键是另一个。首先是代码...

logger.info('About to fetch Regions');
ec2.describeRegionsPromised({}).then(function (data) {
  var addressesPromises = [];

  logger.info('Fetched Regions');

  _.forEach(data.Regions, function (region) {
    var ec2Addresses = AWS.ec2(
      {
        region: region.RegionName,
        endpoint: region.Endpoint
      }
    );
    addressesPromises.push(ec2Addresses.describeAddressesPromised());
  });
  logger.info('About to fetch addresses per region');

  return Promise.all(addressesPromises);
}).then(function (data) {
  logger.info(arguments);
  logger.info('Fetched addresses per region');
  logger.debug(data);
}).catch(function (err) {
  logger.error('There was an error when fetching regions and addresses');
  logger.error(err);
});

正如您在这里注意到的那样,ec2Addresses 是通过调用 AWS.ec2() 而不是 new AWS.ec2() 创建的,这是因为 AWS 承诺的模块创建了对象并且 return 它回来承诺它。 (https://github.com/davidpelayo/aws-promised/blob/master/ecs.js):

'use strict';

var AWS = require('aws-sdk');
var memoize = require('lodash/function/memoize');
var promisifyAll = require('./lib/util/promisifyAll');

function ecs(options) {
  return promisifyAll(new AWS.ECS(options));
}

/**
 * Returns an instance of AWS.ECS which has Promise methods
 * suffixed by "Promised"
 *
 * e.g.
 * createService => createServicePromised
 *
 * @param options
 */
module.exports = memoize(ecs);

问题出在最后一行代码: module.exports = memoize(ecs) 这行代码 正在缓存先前的执行,包括其先前的配置

事实证明,我最终调试了应用程序,我意识到正在执行的承诺数组的区域和端点是相同的,并且那里有一个错误。

通过删除 memoize(ecs),我得到的预期结果是:

info: Fetched addresses per region
debug:  Addresses=[], Addresses=[], Addresses=[], Addresses=[], Addresses=[], Addresses=[PublicIp=XX.XXX.XXX.XXX, AllocationId=eipalloc-XXXXXX, Domain=vpc], Addresses=[], Addresses=[], Addresses=[]

感谢阅读和帮助。

我找到了一种无需创建新 EC2 对象即可请求不同区域地址的方法。换句话说,通过重用现有的 EC2 实例,通过如下方式切换端点:

_.forEach(data.Regions, function (region) {
    //var ec2Addresses = AWS.ec2(
    //  {
    //    region: region.RegionName,
    //    endpoint: region.Endpoint
    //  }
    //);
    var ep = new AWS.Endpoint(region.Endpoint);
    ec2.config.region = region.RegionName;
    ec2.endpoint = ep;
    addressesPromises.push(ec2.describeAddressesPromised());
  });
  logger.info('About to fetch addresses per region');