NodeJS AWS SDK lambda中的多个异步api调用

时间:2018-01-16 11:46:17

标签: node.js callback aws-lambda

我是NodeJS的新手。我对如何在单个lambda函数中完成多个API调用感到困惑。这不是lambda / aws特定的问题,它更多的是与回调相关的混淆。

这是要求。

我想获取所有实例和所有RDS列表,并将它们收集在单个数组中并返回它们。

这里是我编写的一些代码,在语法上我已经验证了。

'use strict';

const AWS = require('aws-sdk');

function getInstancesByRegion(regionName) {
  var instances = [];
  var ec2withRegion = new AWS.EC2({
    region: regionName
  });
  ec2withRegion.describeInstances({}, function(err, data) {
    if (err) {
      console.error(err.toString());
    } else {
      var currentTime = new Date();
      console.log(currentTime.toString());

      for (var r = 0, rlen = data.Reservations.length; r < rlen; r++) {
        var reservation = data.Reservations[r];
        for (var i = 0, ilen = reservation.Instances.length; i < ilen; ++i) {
          var instance = reservation.Instances[i];

          var name = '';
          for (var t = 0, tlen = instance.Tags.length; t < tlen; ++t) {
            if (instance.Tags[t].Key === 'Name') {
              name = instance.Tags[t].Value;
            }
          }
          instances.push({
            id: instance.InstanceId,
            type: instance.InstanceType,
            name: name
          });          
        }
      }
      return instances;
    }
  });
}
function getDatabasesByRegion(regionName) {
  var dbInstances = [];
  var rdsWithRegion = new AWS.RDS({
    region: regionName
  });
  rdsWithRegion.describeDBInstances({}, function(err, data) {
    if (err) {
      console.error(err.toString());
    } else {
      var currentTime = new Date();
      console.log(currentTime.toString());
      for (var r = 0, rlen = data.DBInstances.length; r < rlen; r++) {
        var dbInstance = data.DBInstances[r];
        dbInstances.push({
          id: dbInstance.DBInstanceIdentifier
        });
      }
      return dbInstances;
    }
  });
}

exports.handler = (event, context, callback) => {
  var ec2 = new AWS.EC2();
  var params = {};

  var resources = [];
  ec2.describeRegions(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred

    for (var i = 0; i < data.Regions.length; i++) {
      var regionName = data.Regions[i].RegionName;
      console.log("Current RegionName is " + regionName); 
      resources.push({
        region: regionName,
        instances: getInstancesByRegion(regionName),
        databases: getDatabasesByRegion(regionName)
      });      
    }
  });
  callback(null, resources);
};

1 个答案:

答案 0 :(得分:2)

如果您使用Javascript Promises而不是回调,您的代码可以更清晰。

AWS SDK使用.method(params).promise()代替.method(params, callback)来提供对Promise的支持。

参考:Using Javascript Promises (AWS SDK)

然后,您可以使用promises重写代码。 Promise.all()是您用例的关键。

我就是这样做的......

const AWS = require('aws-sdk')

const ec2 = new AWS.EC2()


function getInstancesByRegion(regionName) {
    const ec2withRegion = new AWS.EC2({
        region: regionName,
    })

    return ec2withRegion.describeInstances({}).promise()
        .then(data => data.Reservations.reduce((acc, reservation) => {
            const instances = reservation.Instances.map(instance => ({
                id: instance.InstanceId,
                type: instance.InstanceType,
                name: instance.Tags.find(tag => tag.Key === 'Name').Value,
            }))

            return acc.concat(instances)
        }, []))
}


function getDatabasesByRegion(regionName) {
    const rdsWithRegion = new AWS.RDS({
        region: regionName,
    })

    return rdsWithRegion.describeDBInstances({}).promise()
        .then(data => data.DBInstances.map(dbInstance => ({
            id: dbInstance.DBInstanceIdentifier,
        })))
}


function getResourcesByRegion(region) {
    return Promise.all([
        getInstancesByRegion(region),
        getDatabasesByRegion(region),
    ])
        .then(results => ({
            region,
            instances: results[0],
            databases: results[1],
        }))
}


exports.handler = (event, context, callback) => ec2.describeRegions({})
    .promise()
    .then((data) => {
        const getResources = data.Regions
            .map(region => getResourcesByRegion(region.RegionName))

        return Promise.all(getResources)
    })
    .then(resources => callback(null, resources))
    .catch(callback)