节点JS异步执行

时间:2020-07-12 06:26:45

标签: javascript node.js asynchronous promise aws-sdk

我刚接触Node Js和异步处理。我正在开发与AWS集成的Discord机器人。我的问题是,我尝试过的所有事情,异步/等待或Promise的包装都没有解决在异步过程完成之前执行其余代码的问题。一般而言,AWS调用通常是异步的,但我正在尝试创建一个同步过程(在添加之前先检查是否已存在该项目)。目前,支票未及时完成,因此该商品被重新添加。

编辑 下面是我编辑的代码和输出

const AWSUtil = require("../utils/aws/awsUtil")

module.exports = async (client, message) => {
  
  const aws = new AWSUtil()
  const tableName = "Discord-Server"
  
  let serverName = message.guild.name.replace(/[^a-zA-Z ]/g, "").replace(' ', '-')
  let serverID = message.guild.id
  
  if (message.member.hasPermission("ADMINISTRATOR")){
    var doesExist = await doesServerExist()
    console.log(`doesExist ----- ${doesExist}`)
    if(!doesExist){
      console.log("5 server is not already enrolled, adding the server...")
      aws.addDynamoDBItem(addServerParams())
      console.log("6 server successfully added")
      message.reply(`${message.guild.name} has been successfully enrolled to SMSAlert!`)
    } else {
      console.log("5 server already enrolled...")
      message.reply(`${message.guild.name} is already enrolled to SMSAlert.`)
    }
   
    } else {
      return message.reply("You do not bave permissions to enroll the server.")
    }

async function doesServerExist(){
  console.log("1 Calling AWS util")
  var response = await aws.getDynamoDBItem(checkExistParams())
  //The below line never prints
  console.log("4 Returning if server exists")
  console.log(Object.keys(response))
  return !Object.keys(response).length == 0
}

function addServerParams(){
return params = {
    TableName:tableName,
    Item:{
        "server-id": serverID,
        "server-name": serverName,
        "topics":[]
    }
};
}

function checkExistParams(){
  return params = {
    TableName: tableName,
    Key:{
        "server-id": { S: serverID }
    }
};
}

}

以下是我的AWSUTIL课

var AWS = require('aws-sdk');

class AWSUtil {
  
  constructor(){
    AWS.config.loadFromPath('./config/aws/config.json');
  }
  
  async getDynamoDBItem(params){
    console.log("2 Get Dynamo Item...")
    const docClient = new AWS.DynamoDB.DocumentClient();
    
    const awsRequest = await docClient.scan(params);
    const result = await awsRequest.promise();
    console.log(result.Items);
    console.log("3 Returning getItem data")
    return results.Items
  }
  
  async addDynamoDBItem(params){
    console.log("Adding a new item...");
    var docClient = new AWS.DynamoDB.DocumentClient();
    const awsRequest = await docClient.put(params);
    const result = await awsRequest.promise();
    console.log("Added item:", JSON.stringify(result))
    //docClient.put(params, function(err, data) {
    //if (err) {
        //console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
    //} else {
        //console.log("Added item:", JSON.stringify(data, null, 2));
    //}
//});
  }
  
  removeDynamoDBItem(params){
    console.log("Attempting to delete...");
    var docClient = new AWS.DynamoDB.DocumentClient();
docClient.delete(params, function(err, data) {
    if (err) {
        console.error("Unable to delete item. Error JSON:", JSON.stringify(err, null, 2));
    } else {
        console.log("DeleteItem succeeded:", JSON.stringify(data, null, 2));
    }
});
  }
}

module.exports = AWSUtil

下面是我的输出

1 Calling AWS Util 
2 Get Dynamo Item...
[
My item
]
3 Returning getItem data

我的主文件中包含以下内容。

if (message.member.hasPermission("ADMINISTRATOR")) {
  if (!doesServerExist()) {
    console.log("server is not already enrolled, adding the server...");
    aws.addDynamoDBItem(addServerParams());
    console.log("server successfully added");
    //return message.reply(`You have successfully enrolled ${message.guild.name} to SMSAlerts.`)
  } else {
    console.log("server already enrolled...");
    //return message.reply(`${message.guild.name} is already enrolled to SMSAlert`)
  }
} else {
  return message.reply("You do not bave permissions to enroll the server.");
}

function isEmptyObject(obj) {
  return !Object.keys(obj).length;
}

function doesServerExist() {
  return isEmptyObject(aws.getDynamoDBItem(checkExistParams()));
}

以下是我的AWS通话

async getDynamoDBItem(params) {
    console.log("Get Dynamo Item...")
    var dynamodb = new AWS.DynamoDB({
        apiVersion: '2012-08-10'
    });
    var response = null
    await dynamodb.getItem(params, function(err, data) {
        if (err) {
            console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
        } else {
            response = data
        }
    }).promise()
    return response
}

2 个答案:

答案 0 :(得分:0)

我不是AWS用户,但是如果您在任务的一个步骤中使用了Promise,则通常意味着您需要为每个步骤处理异步过程。 例如:

async function doesServerExist(){
  const result = await aws.getDynamoDBItem(checkExistParams())
  return isEmptyObject(result)
}

当然,如果要获取doesServerExist的结果,还应该在调用之前使用await来异步获取结果。

答案 1 :(得分:0)

当前正在检查 AWS文档

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Request.html#promise-property

如果您使用dynamodb.getItem,似乎您实际上不需要将回调函数传递给promise,而是等待承诺解决/失败。

所以这行代码是错误的

await dynamodb.getItem(params, function(err,data){
  if (err) {
    console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
  } else {
    response = data
  }
}).promise()

并且应使用promises来实现(第一个参数成功解析,第二个参数根据文档失败是请求的失败)

dynamodb.getItem(params).promise()
 .then( function(data) {
   response = data;
 }, function(err) => {
   console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
 })

并且不确定是否可以使用catch方法代替第二个参数,但是在异步/等待实现中请参见下文

 try {
   const response = await dynamodb.getItem(params).promise()
 } catch(err) {
  console.error("Unable to read item. Error JSON:", JSON.stringify(err, null, 2));
 }