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



我是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);
};

如果你使用 Javascript Promise 而不是回调,你的代码会更干净。

AWS 开发工具包通过使用 .method(params).promise() 而不是 .method(params, callback) 来提供对承诺的支持。

参考:使用 Javascript Promise (AWS 开发工具包(

然后,您可以使用 promise 重写代码。 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)

最新更新