代码之家  ›  专栏  ›  技术社区  ›  havak5

等待AWS SNS发布回调向调用方法返回值

  •  5
  • havak5  · 技术社区  · 8 年前

    当用户请求重置密码时,我试图发送一条短信。我想等待消息发送,以提醒用户是否成功。我目前正在尝试如下操作:

    async function sendResetPasswordTextMessage(req, res) {
        let result = {};
    
        let phoneNumber = req.body.phoneNumber;                
    
        if (phoneNumber === undefined) {                       
            return sendInvalidParametersMessage(res);          
        }                                                      
    
        phoneNumber = phoneNumber.toString();                  
    
        const userProfile = await models.UserProfile.findOne({ 
            where: {                                           
                phoneNumber: phoneNumber                       
            }                                                  
        });                                                    
        ************************** RELEVANT CODE TO ISSUE *************************
        if (userProfile) {
            const message = "Your username is:\n" + userProfile.username;
            const sent = await AWSSNSClient.sendMessage(message, phoneNumber);
    
            if (!sent) {
                result.error = setTitleAndMessage("Error", "An error occurred");
            } else {
                result.success = setTitleAndMessage("Success", "Message sent"); 
            }
        }
        return res.send(result);
        ***************************************************************************
    }
    

    在我的另一个类AWSSNSClient中,我有以下sendMessage函数:

    function sendMessage(message, phoneNumber) {
        const params = { 
            Message: message, 
            MessageStructure: "string", 
            PhoneNumber: "+1" + phoneNumber
        };
        let sent = false;
        sns.publish(params, function(err, data) {
            if (err) {
                console.log(err, err.stack); // an error occurred
            }
            else {
                sent = true;
            }
        });
    
        return sent;
    }
    

    我不知道如何让sendMessage等待sns。发布以在返回自身之前返回。我已经尝试将其作为一个异步方法,并在sns上添加wait。publish,但函数在sent设置为true之前仍然返回。

    我知道消息发送没有错误,因为我正在接收它们,并且没有打印控制台日志。

    6 回复  |  直到 8 年前
        1
  •  20
  •   Necevil    7 年前

    今天,我在谷歌上无意中发现了这一点,试图自己解决这个问题——我现在使用的简短答案是:

    现在,您可以使用Async/Await来实现这一点,并使用调用AWS服务(例如SNS)。promise()扩展,告诉aws sdk使用该服务函数(SNS)的promise-ified版本,而不是基于回调的版本。

    这里唯一需要注意的是,包含函数也必须是异步的,才能使用await语法。

    例如:

    let snsResult = await sns.publish({
        Message: snsPayload,
        MessageStructure: 'json',
        TargetArn: endPointArn
    }, async function (err, data) {
        if (err) {
            console.log("SNS Push Failed:");
            console.log(err.stack);
            return;
        }
        console.log('SNS push suceeded: ' + data);
        return data;
    }).promise();
    

    重要的部分是。promise()在最后。以下是有关以异步/基于承诺的方式使用aws sdk的完整文档: https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html

    为了运行另一个aws sdk任务,您将类似地添加wait和。该函数的promise()扩展(假设可用)。

    对于任何遇到此线程并实际上希望将多个aws sdk承诺推送到一个阵列并等待整个阵列完成的人(不考虑先执行哪个承诺),我的结论如下:

    let snsPromises = [] // declare array to hold promises
    let snsResult = await sns.publish({
        Message: snsPayload,
        MessageStructure: 'json',
        TargetArn: endPointArn
    }, async function (err, data) {
        if (err) {
            console.log("Search Push Failed:");
            console.log(err.stack);
            return;
        }
        console.log('Search push suceeded: ' + data);
        return data;
    }).promise();
    
    snsPromises.push(snsResult)
    await Promise.all(snsPromises)
    

    希望这能帮助那些像我一样通过谷歌偶然发现这一点的人!

        2
  •  9
  •   Tim B0    6 年前

    stackdave真的会等吗?

    Necevil“搜索推送成功将被记录两次”,因为您通过传递回调和使用承诺来混合调用操作。您应该只使用一种方法获得结果

    let snsResult = await sns.publish({
        Message: snsPayload,
        MessageStructure: 'json',
        TargetArn: endPointArn}).promise()
    

    会成功的

        3
  •  4
  •   Vipin Kumar    8 年前

    您可以简单地使用回调。像这样修改您的sendMessge

    function sendMessage(message, phoneNumber, cb) {
        const params = { 
            Message: message, 
            MessageStructure: "string", 
            PhoneNumber: "+1" + phoneNumber
        };
        sns.publish(params, cb);
    }
    

    然后在主文件上提供 callback 这样地

    if (userProfile) {
      const message = "Your username is:\n" + userProfile.username;
      AWSSNSClient.sendMessage(message, phoneNumber, (err, data) => {
        if (err) {
          result.error = setTitleAndMessage("Error", "An error occurred");
        }
        else {
          result.success = setTitleAndMessage("Success", "Message sent");
        }
        res.send(result);
      });
    }
    
        4
  •  3
  •   stackdave    7 年前

    这里是正确更新的API,2018年8月,Necevil answer发送两次短信。

    // using config.env
    AWS.config.region = 'eu-west-1';
    AWS.config.update({
      accessKeyId: process.env.AMAZON_SMS_ID,
      secretAccessKey: process.env.AMAZON_SMS_TOKEN,
    });
    
    // parameters 
    let params = {
       Message: contentSMS,  // here your sms
       PhoneNumber: mobile,  // here the cellphone
     };
    
    
     const snsResult = await sns.publish(params, async (err, data) => {
        if (err) {
           console.log("ERROR", err.stack);
        }
        console.log('SNS ok: ' , JSON.stringify (data));
      });
    
        5
  •  2
  •   Shawn GeertPt    6 年前

    如果您在发送重复的SNS消息时遇到问题,我通过使用AWS的示例修复了此问题:

    // Load the AWS SDK for Node.js
    var AWS = require('aws-sdk');
    // Set region
    AWS.config.update({region: 'REGION'});
    
    // Create publish parameters
    var params = {
      Message: 'MESSAGE_TEXT', /* required */
      TopicArn: 'TOPIC_ARN'
    };
    
    // Create promise and SNS service object
    var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();
    
    // Handle promise's fulfilled/rejected states
    publishTextPromise.then(
      function(data) {
        console.log("Message ${params.Message} send sent to the topic ${params.TopicArn}");
        console.log("MessageID is " + data.MessageId);
      }).catch(
        function(err) {
        console.error(err, err.stack);
      });
    

    通过利用传统 .then() 我能够消除上面评论中提到的重复消息错误。

        6
  •  0
  •   Tony Moreno    4 年前

    您可以创建一个使用promise方法的异步函数

    async function sendMessage(message, phoneNumber){
         const params = { 
            Message: message, 
            PhoneNumber: phoneNumber
        };
      
     return new Promise((resolve, reject) => {
        SNS.publish(params, (err, data) => {
          if (err) {
             console.log("Search Push Failed:");
            console.log(err.stack);
            return reject(err);
          } else {
                console.log('Search push suceeded:' + phoneNumber);
            return resolve(data);
          }
        })
        
        });
      
    }
    

    然后你可以打电话

    var  s=  await sendMessage(message,phoneNumber);