【问题标题】:How do I promisify the AWS JavaScript SDK?如何承诺 AWS JavaScript 开发工具包?
【发布时间】: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

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


【解决方案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));
      猜你喜欢
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 2012-05-24
      • 2015-04-07
      • 2013-07-19
      相关资源
      最近更新 更多