如何承诺 AWS JavaScript 开发工具包?

Posted

技术标签:

【中文标题】如何承诺 AWS JavaScript 开发工具包?【英文标题】:How do I promisify the AWS JavaScript SDK? 【发布时间】:2014-12-16 00:23:06 【问题描述】:

我想通过 Promise 在 javascript 中使用 aws-sdk。

而不是默认的回调样式:

dynamodb.getItem(params, function(err, data) 
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
);

我想使用promise 样式:

dynamoDb.putItemAsync(params).then(function(data) 
  console.log(data);           // successful response
).catch(function(error) 
  console.log(err, err.stack); // an error occurred
);

【问题讨论】:

那么,你试过bluebird.promisifyAll(dynamodb)吗? 与蓝鸟var dynamoDb = Promise.promisifyAll(new AWS.DynamoDB()); 因为 aws-sdk@^2.3.0 已经支持 promise。注意: aws-sdk@^2.3.0 的 bluebird.promisifyAll 将导致错误 module initialization error: TypeError 【参考方案1】:

这个解决方案最适合我:

// Create a promise object
var putObjectPromise = s3.putObject(Bucket: 'bucket', Key: 'key').promise(); 

// If successful, do this:
putObjectPromise.then(function(data) 
 console.log('PutObject succeeded'); )

// If the promise failed, catch the error:
.catch(function(err)  
console.log(err); );

【讨论】:

【参考方案2】:

使用 async/await,我发现以下方法非常干净,并且为我解决了 DynamoDB 的相同问题。这也适用于 ElastiCache Redis。不需要默认 lambda 图像不附带的任何内容。

const promisify = require('util');
const AWS = require("aws-sdk");
const dynamoDB = new AWS.DynamoDB.DocumentClient();
const dynamoDBGetAsync = promisify(dynamoDB.get).bind(dynamoDB);

exports.handler = async (event) => 
  let userId="123";
  let params =     
      TableName: "mytable",
      Key:
          "PK": "user-"+userId,
          "SK": "user-perms-"+userId
      
  ;

  console.log("Getting user permissions from DynamoDB for " + userId + " with parms=" + JSON.stringify(params));
  let result= await dynamoDBGetAsync(params);
  console.log("Got value: " + JSON.stringify(result));

【讨论】:

AWS.CognitoIdentityServiceProvider 对我来说非常有用。添加bind 修复了错误TypeError: this.makeRequest is not a function 谢谢!你是对的,到目前为止,我已经成功地将这种方法用于每个 AWS 开发工具包服务,只需复制、粘贴、重构!我喜欢将它们包装到迷你库中,以最大限度地提高 Lambda 中主要 index.js 代码的可读性。【参考方案3】:

迟到了,但有一个aws-sdk-promise npm 模块可以简化此操作。

这只是添加了一个 promise() 函数,可以像这样使用:

ddb.getItem(params).promise().then(function(req) 
    var x = req.data.Item.someField;
);

编辑:我写这个答案已经有几年了,但由于它最近似乎越来越受欢迎,我想我会更新它:aws-sdk-promise 已弃用,并且aws-sdk 的较新(如过去几年)版本包括内置的 Promise 支持。可以通过config.setPromisesDependency() 配置要使用的promise 实现。

例如,要让aws-sdk 返回Q 承诺,可以使用以下配置:

const AWS = require('aws-sdk')
const Q = require('q')

AWS.config.setPromisesDependency(Q.Promise)

然后promise() 函数将直接返回Q 承诺(使用aws-sdk-promise 时,您必须手动包装每个返回的承诺,例如使用Q(...) 来获得Q 承诺)。

【讨论】:

AWS 版本 3 允许模块化使用 AWS 库,而不需要整个 aws-sdk。当没有全局 AWS 配置时,有没有办法将 DynamoDBClient 的 Promise 依赖设置为第三方 Promise?【参考方案4】:

我相信现在可以在调用后附加.promise() 来承诺给定的方法。

您可以看到它在 2.6.12 https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md#2612 开始引入

您可以在 AWS 的博客 https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/ 中查看它的使用示例

let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();

exports.handler = async (event) => 
    return await lambda.getAccountSettings().promise() ;
;

【讨论】:

请注意,这只适用于某些功能。来自 AWS Docs:“注意:这目前仅适用于返回 AWS.Request 实例的操作。”【参考方案5】:

AWS JavaScript SDK 2.3.0 版本增加了对 Promise 的支持:http://aws.amazon.com/releasenotes/8589740860839559

【讨论】:

不幸的是,Lambda 不支持。 :-( 所以,我一直试图让它在 Lambda 中工作,并刚刚找到您的评论。为什么这在 Lambda 中不起作用?你在哪里找到这些信息的?谢谢! 如果您使用节点 4.3.2,它应该可以在 lambda 下工作,您甚至可以更改 Promise 库。如果您使用的是节点 0.10.x,那么您必须更改 Promise 库,因为它本身不可用。欲了解更多信息,请查看:github.com/aws/aws-sdk-js/blob/… 也许这个答案应该提到如何在 aws-sdk 中启用承诺支持,而不是仅仅链接到概览页面。基本上需要AWS.config.setPromisesDependency(Q.Promise); 来使用Q,并对应于其他promise 实现。更多信息请访问aws.amazon.com/blogs/developer/support-for-promises-in-the-sdk,但请复制内容而不仅仅是链接。【参考方案6】:

CascadeEnergy/aws-promised

我们有一个始终在进行的 npm 模块 aws-promised,它为 aws-sdk 的每个客户端执行 bluebird promisify。我不确定使用上面提到的aws-sdk-promise 模块是否更可取,但就是这样。

我们需要贡献,我们只是花时间承诺我们实际使用的客户,但还有很多事情要做,所以请去做!

【讨论】:

【参考方案7】:

各位, 我一直无法使用Promise.promisifyAll(Object.getPrototypeOf(dynamoDb));

但是,以下对我有用:

this.DYNAMO = Promise.promisifyAll(new AWS.DynamoDB());
...
return this.DYNAMO.listTablesAsync().then(function (tables) 
    return tables;
);

var AWS = require('aws-sdk');
var S3 = Promise.promisifyAll(new AWS.S3());

return S3.putObjectAsync(params);

【讨论】:

您不想将Promise.promisifyAll 作为构造函数调用。请省略第一个new【参考方案8】:

您可以使用执行promisification 的承诺库,例如Bluebird.

这是一个如何承诺 DynamoDB 的示例。

var Promise = require("bluebird");

var AWS = require('aws-sdk');
var dynamoDbConfig = 
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: process.env.AWS_REGION
;
var dynamoDb = new AWS.DynamoDB(dynamoDbConfig);
Promise.promisifyAll(Object.getPrototypeOf(dynamoDb));

不是您可以将Async 添加到任何方法以获取承诺版本。

【讨论】:

对我来说很棒!我正在使用新的 DynamoDB-doc 库。 var docClient = new doc.DynamoDB(); Promise.promisifyAll(Object.getPrototypeOf(docClient));

以上是关于如何承诺 AWS JavaScript 开发工具包?的主要内容,如果未能解决你的问题,请参考以下文章

使用字节的 AWS Rekognition JavaScript 开发工具包

如何正确解析 bs-typeahead 的 javascript 承诺

如何使用 AWS 开发工具包进行身份验证

如何在节点 AWS 开发工具包代码中使用 AWS ECS 任务角色

AWS API JavaScript SDK CORS 错误

如何在使用Java AWS开发工具包创建AWS EC2时提供实例名称