Search code examples
javascriptes6-promisetwilio-apiecmascript-2016twilio-programmable-chat

Javascript Chain of promises in For Loop


I am using twilio platform ... and I am testing my code... but I dont understand what happen when I try to get a channel from channelDescriptor... I have this code:

function processChannelPage(page)
            {
                var items = page.items;
                that.channels = that.channels || [];

                for (let c = 0, p = Promise.resolve(); c < items.length; c++) 
                {
                    p = p.then(function() {
                        let channelDescriptor = items[c];                        
                        console.log("SID ", channelDescriptor.sid);
                        
                         
                        getPreviousMessages(channelDescriptor, that)
                        .then(function() {
                            console.log("resuelto msg", channelDescriptor.sid);
                            return Promise.resolve();
                        }); 

                    });    
                }

                ..............
            }

            that.client.getUserChannelDescriptors().then(function (paginator) {
                processChannelPage(paginator);
            });

    function getPreviousMessages(channelDescriptor, chat) {
        return new Promise(resolve => { 
            console.log("p2.....step0.....", channelDescriptor.sid);     
            console.log("p2.....step1.....", channelDescriptor.sid);
            let promise = chat.getChannel(channelDescriptor.sid); 
            console.log(promise);       
            return promise.then(channel => {
                console.log("p2.....step2.....", channelDescriptor.sid); 
                return channel;
            });
        });
    }
 

    TwilioChat.prototype.getChannel = function (channel_sid) {
        console.log("I am in getChannel.....");
        for (var channel in this.channels) {
            if (this.channels[channel].sid == channel_sid) {
                return this.channels[channel].getChannel();
            }
        }
        return null;
    };

I understand that TwilioChat.prototype.getChannel returns a Promise, then I know I need to evaluate this promise using THEN like this

chat.getChannel(channelDescriptor.sid).then

But I see this results:

SID  CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:147 p2.....step0..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:148 p2.....step1..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:72 SID  CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:147 p2.....step0..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:148 p2.....step1..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:150 p2.....step2..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:150 p2.....step2..... CH369ca3cc46d74886b031a52fd2e7dc29

My question is... why this log twilio_helper.js:150 p2.....step2 I see outside my Chain of promises. I need to see this result:

SID  CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:147 p2.....step0..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:148 p2.....step1..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:150 p2.....step2..... CH09c567eeebab4dabb5fa8594a44d774e

twilio_helper.js:72 SID  CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:147 p2.....step0..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:148 p2.....step1..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:150 p2.....step2..... CH369ca3cc46d74886b031a52fd2e7dc29

First channelDescriptor.... all promises executed.... next ChannelDescriptor... all promises executed... In other words the loop advance in order by each channelDescriptor... Please I need only Promises... not Async/Await... because I need this also works in IExplorer. Can you help me with this promises? Thank you very much!

Ok!!!! Ok I change my code like these modifications....

TwilioChat.prototype.getChannel = function(channel_sid){
    console.log("I am in getChannel.....");
    for (var channel in this.channels) {
        if (this.channels[channel].sid == channel_sid) {
            return this.channels[channel].getChannel();
        }
    }
    reject("error");
};


function getPreviousMessages(channelDescriptor, chat) {
    return new Promise(resolve => { 
        console.log("p2.....step0.....", channelDescriptor.sid);     
        console.log("p2.....step1.....", channelDescriptor.sid);
        let promise = chat.getChannel(channelDescriptor.sid); 
        console.log(promise);       
        return promise.then(channel => {
            console.log("p2.....step2.....", channelDescriptor.sid); 
            resolve(channel); // I Resolve my New Promise
        });
    });
}

But my test always results this:

I see....this code log....

SID  CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:147 p2.....step0..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:148 p2.....step1..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:72 SID  CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:147 p2.....step0..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:148 p2.....step1..... CH369ca3cc46d74886b031a52fd2e7dc29
twilio_helper.js:388 I am in getChannel.....
twilio_helper.js:392 Promise {<pending>}
twilio_helper.js:150 p2.....step2..... CH09c567eeebab4dabb5fa8594a44d774e
twilio_helper.js:150 p2.....step2..... CH369ca3cc46d74886b031a52fd2e7dc29

p2.....Step2..... is outside my loop.... Really I dont understand.


Solution

  • Avoid the Promise constructor antipattern in getPreviousMessages, make sure that getChannel always returns a promise, and don't forget to return your promises from the then callbacks in processChannelPage.

    function processChannelPage(page) {
        var items = page.items;
        that.channels = that.channels || [];
    
        for (let c = 0, p = Promise.resolve(); c < items.length; c++) {
            p = p.then(function() {
                let channelDescriptor = items[c];                        
                console.log("SID ", channelDescriptor.sid);
    
                return getPreviousMessages(channelDescriptor, that).then(function() {
    //          ^^^^^^
                    console.log("resuelto msg", channelDescriptor.sid);
                }); 
            });
        }
        …
        return p;
    }
    

    that.client.getUserChannelDescriptors().then(function (paginator) {
        return processChannelPage(paginator);
    //  ^^^^^^
    });
    

    function getPreviousMessages(channelDescriptor, chat) {
        console.log("p2.....step0.....", channelDescriptor.sid);     
        console.log("p2.....step1.....", channelDescriptor.sid);
        let promise = chat.getChannel(channelDescriptor.sid); 
        console.log(promise);       
        return promise.then(channel => {
    //  ^^^^^^
            console.log("p2.....step2.....", channelDescriptor.sid); 
            return channel;
        });
    }
    

    TwilioChat.prototype.getChannel = function (channel_sid) {
        console.log("I am in getChannel.....");
        for (var channel in this.channels) {
            if (this.channels[channel].sid == channel_sid) {
                return this.channels[channel].getChannel();
            }
        }
        return Promise.resolve(null);
    //         ^^^^^^^^^^^^^^^^    ^
    };