5

当用户请求重置密码时,我正在尝试发送短信。我想等待发送消息以提醒用户它是否成功。我目前正在尝试按以下方式进行操作:

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.publish 在它返回之前返回。我尝试将其设为异步方法并在 sns.publish 上添加等待,但该函数仍会在 send 设置为 true 之前返回。

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

4

6 回答 6

20

今天通过谷歌偶然发现了这一点,我自己试图弄清楚这一点——我现在正在使用的简短回答:

您现在可以使用 Async/Await 执行此操作 — 并使用 .promise() 扩展名调用 AWS 服务(例如 SNS),以告诉 aws-sdk 使用该服务函数 (SNS) 的承诺化版本而不是调用基于回的版本。

这里唯一需要注意的是包含函数也必须是异步的才能使用 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 任务,您将类似地将 await 和 .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)

希望能帮助像我一样通过谷歌随机偶然发现的人!

于 2018-07-12T21:59:30.717 回答
8

stackdave 真的会等吗?

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

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

会成功的

于 2019-01-23T11:49:46.790 回答
4

你可以简单地使用回调。像这样修改你的 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);
  });
}
于 2017-12-14T05:21:49.913 回答
3

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

// 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));
  });
于 2018-08-13T13:06:46.750 回答
2

如果您在发送重复的 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()我能够消除上面评论中提到的重复消息错误。

于 2019-05-02T19:52:14.587 回答
0

您可以创建一个使用 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);
于 2021-05-13T07:34:34.217 回答