Lambda 中的 DynamoDB updateItem 以静默方式失败

Chu*_*ams 1 amazon-web-services amazon-dynamodb aws-lambda

我试图用 Lambda 函数实现一个简单的计数器,但是每当我测试它时,下面的 updateItem 根本不起作用:回调中的任何日志语句都没有运行,当然还有表中的相关计数器永远不会更新。这是我的 lambda 函数:

'use strict';
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });

let params = {
    TableName: 'Counters',
    Key: {
        'name': { S: 'global' }
    },
    UpdateExpression: 'SET val = val + :inc',
    ExpressionAttributeValues: {
        ':inc': { N: '1' }
    },
    ReturnValues: 'ALL_NEW'
};

exports.handler = async(event) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params, function(err, data) {
        console.log("In updateItem callback");
        if (err)
            console.log(err, err.stack);
        else
            console.log(data);
    });

    console.log("Updated counter");

    const response = {
        statusCode: 200,
        body: JSON.stringify('Counter updated'),
    };
    return response;
};

Run Code Online (Sandbox Code Playgroud)

这是测试的输出:

Response:
{
  "statusCode": 200,
  "body": "\"Counter updated\""
}

Request ID:
"80e92299-2eea-45e4-9c68-54ccf87199c5"

Function Logs:
START RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5 Version: $LATEST
2019-05-07T11:34:21.931Z    80e92299-2eea-45e4-9c68-54ccf87199c5    Invoked counter-test
2019-05-07T11:34:21.934Z    80e92299-2eea-45e4-9c68-54ccf87199c5    Updated counter
END RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5
REPORT RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5  Duration: 275.91 ms Billed Duration: 300 ms     Memory Size: 128 MB Max Memory Used: 67 MB  
Run Code Online (Sandbox Code Playgroud)

如您所见,没有运行 updateItems 回调中的日志语句。

如果我尝试使用aws dynamodb它从命令行更新计数器确实有效,但是:

$ aws dynamodb update-item \
  --table-name Counters \
  --key '{"name": { "S": "global" }}' \
  --update-expression 'SET val = val + :inc' \
  --expression-attribute-values '{":inc": {"N": "1"}}' \
  --return-values ALL_NEW \
  --output json
{
    "Attributes": {
        "name": {
            "S": "global"
        },
        "val": {
            "N": "129"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

jog*_*old 5

这是由于 Javascript 的异步特性。

该方法updateItem是异步的,您不会在返回之前等待回调被触发(您开始updateItem操作然后立即返回响应)。

如果你想保持回调模式,你应该这样做:

exports.handler = (event, context, callback) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params, function(err, data) {
        console.log("In updateItem callback");
        if (err) {
            console.log(err, err.stack);
            callback(err);
        } else {
            console.log(data);
            console.log("Updated counter");
            const response = {
                statusCode: 200,
                body: JSON.stringify('Counter updated'),
            };
            callback(null, response);
        }
    });
};
Run Code Online (Sandbox Code Playgroud)

使用承诺:

exports.handler = (event, context, callback) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params).promise()
        .then((data) => {
            console.log(data);
            console.log("Updated counter");

            const response = {
                statusCode: 200,
                body: JSON.stringify('Counter updated'),
            };
            callback(null, response);          
        });
        .catch((err) => {
          console.log(err, err.stack);
          callback(err);
        })
};
Run Code Online (Sandbox Code Playgroud)

使用await(推荐):

exports.handler = async (event) => {
    try {
        console.log("Invoked counter-test");

        const data = await dynamodb.updateItem(params).promise();
        console.log(data);

        console.log("Updated counter");

        const response = {
            statusCode: 200,
            body: JSON.stringify('Counter updated'),
        };
        return response;      
    } catch (err) {
      console.log(err, err.stack);
      throw err;
    }
};
Run Code Online (Sandbox Code Playgroud)

另请参阅了解异步 JavaScript通过示例深入了解 JavaScript 异步和等待以及适用于 Javascript 的 AWS 开发工具包 - 使用 JavaScript 承诺