使用适用于节点和蓝鸟的AWS-SDK从promises返回的数据

时间:2015-08-14 17:10:09

标签: node.js amazon-ec2 promise bluebird aws-sdk

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

.then

这样做没问题,但我的问题是我正在查看第二个data承诺回调函数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] 参数,其数据是长度相同的数组第一次请求时返回的区域

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

返回的区域如下(它实际上是格式化的JSON):

{ Regions: [] } //and so on

在JSON中它将是:

[ { 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] ] } ]

返回的弹性IP如下:

Macbook:sp user$ find .
.
./build.sbt
./project
./project/plugin.sbt
./src
./src/main
./src/main/scala
./src/main/scala/MySimpleApp.scala

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

我希望在第二个响应中每个区域的值解析,其余区域设置为null,undefined或类似。

总结一下。我不明白为什么解析一系列promises的值(使用.all)会在每个点中得到一组相同的值 - 而不是预期的结果。

这里发生了什么?提前谢谢!

2 个答案:

答案 0 :(得分:0)

我发现了这个问题。 由于@ 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承诺的模块会创建对象并将其返回并对其进行宣传。 (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=[]

感谢阅读和帮助。

答案 1 :(得分:0)

我发现了一种在不创建新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');