ErnieKev
ErnieKev

Reputation: 3041

Execute Multiple async operation at gets notified when all of them completes (Typescript)

I have the following data structure in my firebase

- ActionSheet
    - PendingApproval
        - SomeKey1
            - user: 1
            - data: 'walk the dog'
        - SomeKey2
            - user: 2
            - data: 'brush the cat'
    - Approved
        - SomeKey3
            - user: 1
            - data: 'feed fish'

I want to download all data from user 1 in this structure such that I can display to the user to 'walk the dog' and 'feed fish'

At the moment this is how I do it. I am "chaining" the calls such that the 2nd call does not start until the first one finishes.

ngOnInit() {
this.databaseService.searchCurrentUserPendingApproval()
    .first()
    .subscribe(results => {

        for (let result of results) {
            this.mySubmissions.push(result);
        }

        this.databaseService.searchCurrentUserApprovedAction()
            .first()
            .subscribe(results => {

                for (let result of results) {
                    this.mySubmissions.push(result);
                }

                // do some logic to the this.mySubmissio array at this point
                doSomething(this.mySubmission);

            }, error => {
                console.log('Error download Actioned Timesheet', error)
            })

    }, error => {
        console.log('error retreiving pending submission from firebase', error)
    })
}

searchCurrentUserPendingTimesheets(key: string) {
    let path = '/ActionSheet/PendingApproval' + key;
    return this.af.database.list(path, {
        query: {
            orderByChild: 'user',
            equalTo: 1
        }
    })
}

// search for own timesheet in firebase
searchCurrentUserActionedTimesheets(key: string) {
    let path = '/ActionSheet/Approved' + key;
    return this.af.database.list(path, {
        query: {
            orderByChild: 'user',
            equalTo: 1
        }
    })
}

This works. However, the biggest problem is that this is a terrible way of doing it and it would be slow for larger "chain". As the two query does not depend on each other, a better way to do it would be to to query the two branch at the same time and get notified when both of the operation completes (Doesn't matter which one comes back first as I will sort the array at the end').

In other words, I want to run doSomething(this.mySubmission) once all of the async calls mentioned is completed. Is there a proper typescript way to achieve this?

Note. When I was working with Swift, I was able to achieve this with dispath_group_enter/dispatch_group_leave.

Upvotes: 1

Views: 61

Answers (2)

Tuong Le
Tuong Le

Reputation: 19240

You can try with forkJoin as below:

Observable.forkJoin(
    this.databaseService.searchCurrentUserPendingApproval().first(),
    this.databaseService.searchCurrentUserApprovedAction().first()
).subscribe([pendingResults, approvedResults] => {
    this.mySubmissions = this.mySubmissions.concat(pendingResults, approvedResults);
    doSomething(this.mySubmissions);
}, error => console.log('Error download Actioned Timesheet', error))

Upvotes: 1

kemsky
kemsky

Reputation: 15308

You can wait for multiple observables using forkJoin.

Upvotes: 1

Related Questions