等待AWS SNS发布回调以将值返回给调用方法

hav*_*ak5 2 javascript node.js amazon-sns async-await aws-sdk-js

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

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);
    ***************************************************************************
}
Run Code Online (Sandbox Code Playgroud)

在我的其他类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;
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何使sendMessage等待sns.publish在它返回之前返回.我已经尝试使它成为异步方法并在sns.publish上添加await,但该函数仍然在发送之前返回设置为true.

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

Nec*_*vil 10

通过谷歌试图在今天自己解决这个问题偶然发现 - 我现在使用的简短回答:

您现在可以使用Async/Await执行此操作 - 并使用.promise()扩展来调用AWS服务(例如SNS),以告知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();
Run Code Online (Sandbox Code Playgroud)

最重要的部分是那里的.promise().有关以异步/承诺方式使用aws-sdk的完整文档,请访问:https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/using-promises.html

为了运行另一个aws-sdk任务,你可以类似地为该函数添加await和.promise()扩展(假设它是可用的).

对于遇到这个线程并且实际上只是想将多个aws-sdk promises推送到数组并等待该WHOLE数组完成的任何人(不考虑首先执行哪个promise)我最终得到了类似这样的东西:

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)
Run Code Online (Sandbox Code Playgroud)

希望能帮助那些通过谷歌随意绊倒的人像我一样!

  • 我遇到了一个问题,即使用“promise()”时事件发布了两次 /sf/ask/4249779411/。同样奇怪的是,使用“promise()”时仍然需要回调 (2认同)

Tim*_* B0 7

stackdave 真的会等吗?

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

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

会做的伎俩


Vip*_*mar 4

您只需使用回调即可。像这样修改你的sendMessge

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

然后在你的主文件上你可以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);
  });
}
Run Code Online (Sandbox Code Playgroud)