简体   繁体   中英

JavaScript: Promise chaining in foreach loop

I'm new to javascript promises and am having difficulty using them with a collection of elements. Within the collection, I perform an operation which returns a promise. Once the entire operation (including all the Promises in the collection) has completed, I need to perform another set of operations. The promises within the collection need to go in sequence.

I have tried the following approach:

public cleanup(onCleanupComplete: any): void {
        if (this._app == null) return; //this._app comes out of an external API

       // Below line of code won't compile, it is just for illustration. 
       // I'm trying to show that I need a promise in return from method
        this.removeConference(0).then(() => {
              // Do additional clean up operation and call onCleanupComplete
                onCleanupComplete(true, null);                
        });

    }

    private removeConference(i : number) {
        if (this._app.conversationsManager.conversations == null 
           || i === this.conversationLength)
            return; // this.conversationLength equals initial 
                    // number of elements in collection 
                    // How do I return a promise here?

        var conversation = this._app.conversationsManager.conversations(0);
                console.log("app.cleanup.leave", `Leaving conversation ${conversation}`);
        conversation.leave().then(() => {
                console.log("app.cleanup.leave", `Conversation ${conversation} left successfully`);
            this.app.conversationsManager.conversations.remove(conversation);
 _           this.removeConference(i);
        });
    }

What should I return from removeConference once all the conversations in collection are removed?

So this is something that nabbed me early on in understanding promises. You need to get ALL of your code away from the practice of passing in a callback, and then simply using the promise to call that. Instead, to keep the continuous nature of promises, you want to just return promises to the calling function, unless your function is the one that should decide what to do afterward. So, your code should look something like this.

public cleanup(onCleanupComplete: any):Promise<any> {
        if (this._app == null) return; //this._app comes out of an external API

       // Below line of code won't compile, it is just for illustration. 
       // I'm trying to show that I need a promise in return from method
       var promiseArray = [];
       for (var i = 0; i < this.conversationLength; i++) {
         promiseArray.push(removeConference(i));
       }
       return Promise.all(promiseArray);

    }

    private removeConference(i : number):Promise<any> {
        if (this._app.conversationsManager.conversations == null 
           || i === this.conversationLength)
            return Promise.resolve(true);

        var conversation = this._app.conversationsManager.conversations(0);
                console.log("app.cleanup.leave", `Leaving conversation ${conversation}`);
        return conversation.leave().then(() => {
                console.log("app.cleanup.leave", `Conversation ${conversation} left successfully`);
            this.app.conversationsManager.conversations.remove(conversation);
            this.removeConference(i);
        });
    }

I'm not 100% sure this compiles correctly, but hopefully it helps conceptually. Promise.all is really the key function here - it takes an array of promises, and creates a matching "control promise" that only resolves when all of them have.

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