通过节点的异步/等待不需要按预期顺序返回结果 - 使用啥正确模式?

Posted

技术标签:

【中文标题】通过节点的异步/等待不需要按预期顺序返回结果 - 使用啥正确模式?【英文标题】:Async / Await through Node require no returning results in anticipated order - What is correct pattern to use?通过节点的异步/等待不需要按预期顺序返回结果 - 使用什么正确模式? 【发布时间】:2020-04-18 06:49:36 【问题描述】:

我正在使用标准节点要求模式,该模式需要文件 (send.js) 并允许访问这些模块导出的功能。

如果我在标准回调模式中使用所有必需的模块,我会得到预期的结果和正确的执行顺序。

但是,如果我尝试转到等待/异步模式,则函数执行不正确(随机)。

在 send.js 中:

var request = require(`request`);
module.exports = 
    message: function message(psid,text,callback) 
        var options = 
            headers: 
                'Content-Type': `application/json`
            ,
            url:`https://graph.facebook.com/v4.0/me/messages?access_token=12345`,
            body:JSON.stringify(
                'messaging_type': `RESPONSE`,
                'recipient':
                    'id':``+psid+``
                ,
                'message': 
                    'text': text
                
            )
        ;
        request.post(options, function (err, res, body)
            if(err)
                console.log(err);
                callback(err)
            
            else
              callback(null,body)
            
        );
    ,

在 app.js 中:

回调模式 - 适用于嵌套函数、按顺序执行的函数:

send.message(psid,'text'function(err,result)
        send.message(psid,result,function(err,response)
            console.log(response);
        );
    );

异步等待模式 - 以错误的顺序返回消息,随机执行顺序:

async function test()
    const one = await send.getUser(psid,'text',function());
    const two = await send.message(psid,`1`,function());
    const three = await send.message(psid,`2`,function());
    const four = await send.message(psid,`3`,function());
    const five = await send.message(psid,`4`,function());

test();

这是因为所需的模块使用回调 - 如果是这样,我如何转换 send.js 以便我可以在 app.js 中使用异步等待模式?

谢谢。

【问题讨论】:

send.messagesend.getUser 是否返回 Promise?如果没有,那么await 将在那里什么都不做。 你的函数没有用 async 声明,也没有返回一个 Promise。您的消息 getUser 应使用 async 关键字声明并返回一个承诺 要么是回调,要么是 promise/async-await。将两者混合(就像您在 await message(...., function() ) 中所做的那样没有多大意义。 【参考方案1】:

不使用外部库,您可以返回 Promise 而不是使用 callback

您的 send.js 可能是:

var request = require(`request`);
module.exports = 
    message: function message(psid, text) 
        return new Promise((resolve, reject) => 
            var options = 
                headers: 
                    'Content-Type': `application/json`
                ,
                url: `https://graph.facebook.com/v4.0/me/messages?access_token=12345`,
                body: JSON.stringify(
                    'messaging_type': `RESPONSE`,
                    'recipient': 
                        'id': `` + psid + ``
                    ,
                    'message': 
                        'text': text
                    
                )
            ;
            request.post(options, function (err, res, body) 
                if (err) 
                    return reject(err)
                
                else 
                    return resolve(body)
                
            );
        )
    

然后你可以像@Satvik-Daga 的回答一样使用它:

const firstBody = await send.message(psid,`1`);

【讨论】:

非常感谢@taymer 的这个补充,这意味着我知道现在可以在其他领域做出承诺。非常感谢您的意见。【参考方案2】:

async/await 仅适用于承诺。您需要修改 send.js 以使用 Promise。 一种方法是使用request-promise 而不是请求模块。

var rp = require(`request-promise`);
module.exports = 
    message: function message(psid,text) 
        var options = 
            method: 'POST',
            headers: 
                'Content-Type': `application/json`
            ,
            uri:`https://graph.facebook.com/v4.0/me/messages?access_token=12345`,
            body:
                'messaging_type': `RESPONSE`,
                'recipient':
                    'id':``+psid+``
                ,
                'message': 
                    'text': text
                
            
        ;
        return rp(options);
    ,


async function test()
    const one = await send.getUser(psid);
    const two = await send.message(psid,`1`);
    const three = await send.message(psid,`2`);
    const four = await send.message(psid,`3`);
    const five = await send.message(psid,`4`);

test();

您还需要修改 getUser 方法以使用 request-promise。

【讨论】:

非常感谢@satvik daga。一切都按预期工作,现在通过这篇文章完全理解了从回调/使用 Promise 的转换。很棒的社区。​​span>

以上是关于通过节点的异步/等待不需要按预期顺序返回结果 - 使用啥正确模式?的主要内容,如果未能解决你的问题,请参考以下文章

颤振异步等待未按预期工作

无法从异步函数获取返回值,等待未按预期工作(Vue API 服务)

应用服务性能优化-异步

dottrace 异步等待支持不起作用

同步和异步 各是啥啊。能举例说明吗?

vue同时异步执行等待结果返回然后再处理