node.js - NodeJS 和 AWS Lambda 的异步等待问题

标签 node.js amazon-web-services async-await aws-lambda

我目前正在为我的 AWS 项目开发一个 Lamba 函数调用,但由于我不是异步函数的专家,它似乎正在崩溃,我整理的代码是:

const AWS = require("aws-sdk");
const game = require('game-api');
const uuid = require("uuid");

AWS.config.update({
  region: "us-east-1"
});

exports.handler = async (event, context, callback) => {

    //set db
    var documentClient = new AWS.DynamoDB.DocumentClient()

    //params
    const params = {
        Item: {
            'id': uuid.v1(),
            'player_1_name': null,
            'player_1_network': null,
            'player_1_matches': 0,
            'player_1_kills': 0,
            'player_1_last_updated': 0,
            'player_2_name': null,
            'player_2_network': null,
            'player_2_matches': 0,
            'player_2_kills': 0,
            'player_2_last_updated': 0,
            'match_id': 0,
            'status': 0
        },
        TableName : 'matches'
    };

    var matchData = JSON.parse(event.body);

    //player 1
    const player_1_name = matchData.player_1_name ? matchData.player_1_name : null;
    const player_1_network = matchData.player_1_network ? matchData.player_1_network : null;

    //player 2
    const player_2_name = matchData.player_2_name ? matchData.player_2_name : null;
    const player_2_network = matchData.player_2_network ? matchData.player_2_network : null;

    //match data
    const match_id = matchData.match_id ? matchData.match_id : 0;

    //game object
    let gameAPI = new game(
        [
            "email@email.com",
            "password"
        ]
    );

    //gameAPI.login() returns a Promise()
    await gameAPI.login().then(() => {

        //check stats for player 1, getStats returns a Promise()
        gameAPI.getStats(player_1_name, player_1_network).then(stats => {

            params.Item.player_1_matches = stats.lifetimeStats.matches;
            params.Item.player_1_kills = stats.lifetimeStats.kills;

        }).catch(err => {

            //error! we must work out what to do here!
            console.log(err);

        });

        //example insert
        documentClient.put(params, function(err, data){
            return callback(err, data);
        });

    }).catch(err => {
        console.log("We failed to login!");
        console.log(err);
    });

};

这个逻辑似乎有缺陷,因为没有任何内容被扔到我的 AWS 日志中?我的想法是将请求发送到函数并让它尽快完成,这样我就可以向 Lambda 发送 200 响应,有人能给我指出正确的方向吗?

最佳答案

当使用async/await时,你不需要使用callback,也不需要陷入Promise Hell。

只需等待您的 promise 并获取结果。这里最大的优点是它看起来就像您的代码是同步的。

这是您重构的代码:

const AWS = require("aws-sdk");
const game = require('game-api');
const uuid = require("uuid");

AWS.config.update({
  region: "us-east-1"
});

exports.handler = async (event) => {

    //set db
    var documentClient = new AWS.DynamoDB.DocumentClient()

    //params
    const params = {
        Item: {
            'id': uuid.v1(),
            'player_1_name': null,
            'player_1_network': null,
            'player_1_matches': 0,
            'player_1_kills': 0,
            'player_1_last_updated': 0,
            'player_2_name': null,
            'player_2_network': null,
            'player_2_matches': 0,
            'player_2_kills': 0,
            'player_2_last_updated': 0,
            'match_id': 0,
            'status': 0
        },
        TableName : 'matches'
    };

    var matchData = JSON.parse(event.body);

    //player 1
    const player_1_name = matchData.player_1_name ? matchData.player_1_name : null;
    const player_1_network = matchData.player_1_network ? matchData.player_1_network : null;

    //player 2
    const player_2_name = matchData.player_2_name ? matchData.player_2_name : null;
    const player_2_network = matchData.player_2_network ? matchData.player_2_network : null;

    //match data
    const match_id = matchData.match_id ? matchData.match_id : 0;

    //game object
    let gameAPI = new game(
        [
            "email@email.com",
            "password"
        ]
    );

    //gameAPI.login() returns a Promise()
    await gameAPI.login()

    const stats = await gameAPI.getStats(player_1_name, player_1_network)
    params.Item.player_1_matches = stats.lifetimeStats.matches;
    params.Item.player_1_kills = stats.lifetimeStats.kills;

        //example insert
    await documentClient.put(params).promise();

};

如果您需要处理异常(您应该),只需将您的await 调用包装在try/catch block 中,如下所示:

try {
   console.log(await somePromise)
} catch (e) {
   console.log(e)
}

上面的代码片段相当于:

somePromise.then(console.log).catch(console.log)

最大的区别是您不需要链接 Promise/异步代码来保持执行顺序,因此我强烈建议您选择 async/await 方法并忘记 .then().catch()

关于node.js - NodeJS 和 AWS Lambda 的异步等待问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55142707/

相关文章:

javascript - 如何从虚拟内存中为node.js提供html+js服务?

amazon-web-services - AWS角色和用户没有任何政策,为什么我仍然可以访问K8s集群?

c# - SNS - JSON 消息正文解析失败

javascript - 只有在父组件的异步方法完成后才渲染子组件

node.js - 使用 Angular 和 Nodejs 将文件保存到 mongodb

javascript - Node.js EJS 快速验证器

MongoDB Compass 连接问题与 Ec2 实例访问亚马逊 documentDB 集群

c# - Parallel.ForEach 是否使用 ASP.NET 线程池中的线程?

python - 取消 python asyncio 中的嵌套协程

javascript - Mongoose - 在保存文档之前为每个对象生成 ObjectID