Home > Software design >  I can't figure out how to use Promise correctly in this context
I can't figure out how to use Promise correctly in this context

Time:06-11

webhookClient.send(temp); executed earlier than temp['files'] = [link]; contains ; I need to wait for this. tg_bot.getFileLink - promise How to sync it correctly?

 let contains = 0
let temp = {
    username: `${msg.from.first_name} tg`,
};
const user_profile = tg_bot.getUserProfilePhotos(msg.from.id);
user_profile
    .then(function (res) {
        tg_bot.getFileLink(res.photos[0][0].file_id)
            .then(link => { temp['avatarURL'] = link;})
            .then( () => {
                if (msg.text !== undefined) {
                    temp['content'] = msg.text;
                    contains  ;}})
            .then(() => {
                if (msg.photo !== undefined) {
                    let link = tg_bot.getFileLink(msg.photo.slice(-1)[0].file_id)
                        .then(link =>{
                                temp['files'] = [link];
                                contains  ;})}})
            .then(() => {
                    if (contains <= 0) temp['content'] = 'empty';
                    console.log(temp);
                    webhookClient.send(temp);})

});

CodePudding user response:

This code really lends itself to using await so you don't have to deal with nested .then() handlers and it's much easier to deal with branching in your code flow. This is a classic example of why await was invented (to make code like this simpler to write and debug).

This assumes it is inside an async tagged function:

let contains = 0
let temp = {
    username: `${msg.from.first_name} tg`,
};

const res = await tg_bot.getUserProfilePhotos(msg.from.id);
temp['avatarURL'] = await tg_bot.getFileLink(res.photos[0][0].file_id);
if (msg.text !== undefined) {
    temp['content'] = msg.text;
    contains  ;
}
if (msg.photo !== undefined) {
    let link = await tg_bot.getFileLink(msg.photo.slice(-1)[0].file_id);
    temp['files'] = [link];
    contains  ;
}
if (contains <= 0) {
    temp['content'] = 'empty';
}
webhookClient.send(temp);

If you wanted to make this work without await, using only .then(), then you just have to chain the conditional call to getFileLink() (by returning its promise) so that the next .then() block will wait for it:

let contains = 0;
let temp = {
    username: `${msg.from.first_name} tg`,
};
const user_profile = tg_bot.getUserProfilePhotos(msg.from.id);
user_profile.then(function(res) {
    return tg_bot.getFileLink(res.photos[0][0].file_id).then(link => {
        temp['avatarURL'] = link;
    }).then(() => {
        if (msg.text !== undefined) {
            temp['content'] = msg.text;
            contains  ;
        }
        if (msg.photo !== undefined) {
            return tg_bot.getFileLink(msg.photo.slice(-1)[0].file_id).then(link => {
                temp['files'] = [link];
                contains  ;
            });
        }
    }).then(() => {
        if (contains <= 0) {
            temp['content'] = 'empty';
        }
        console.log(temp);
        webhookClient.send(temp);
    });
});

Note how I've also flattened the nesting and combined .then() blocks that didn't have to be separate.


Note: both these implementations needs error handling. The first needs a try/catch around it to catch any rejections from any of the await statements (or the caller needs to catch the rejected promise the async function would return.

The second implementation needs a .catch() at the end of the chain.

  • Related