简体   繁体   中英

Async / Await through Node require no returning results in anticipated order - What is correct pattern to use?

I'm using a standard node require pattern that requires a file (send.js) and allows access to functions those modules export.

If I use all the required modules in a standard callback pattern, I get the anticipated result and proper order of execution.

However, if I try to move to an await / async pattern, the function execution is incorrect (random.)

In 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)
            }
        });
    },
}

In app.js:

Callback patterns - Works for nested functions, functions executed in sequence:

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

Async Await patterns - Returns messages in wrong order, random execution order:

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();

Is this because the required modules use callbacks - and if so, how do I transform send.js so that I may use the async await pattern in app.js?

Thank you.

async/await only works with promises. You need to modify send.js to use promises. One way to do this is to use request-promise instead of the request module.

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();

You need to modify the getUser method to use request-promise as well.

Without using an external library you can return a Promise instead of using the callback .

Your send.js could be:

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)
                }
            });
        })
    }
}

Then you can use it as in the answer of @Satvik-Daga:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM