5

I'm wondering if observable or promise can be used in the following use case in angular 2:

There are two asynchronized upload tasks. I'd like to know how I can detect both tasks are finished.

My upload task (implemented in promise but it's easily be changed to observable if needed) is like this:

myService.upload('upload1').then(() => {
})

myService.upload('upload2').then(() => {
})

How to chain these two events together in either promise or observable so that I know both tasks are finished? Thanks

Bagusflyer
  • 12,675
  • 21
  • 96
  • 179

4 Answers4

7

You can use one of the Combining Operators with observables. Observable.zip(), for example, works with promises...

Observable.zip(
    first,
    second,
    function (firstResolvedValue, secondResolvedValue) {
        return firstResolvedValue && secondResolvedValue;
    }
)

zip accepts a variable number of Observables or Promises as parameters, followed by a function that accepts one item emitted by each of those Observables or resolved by those Promises as input and produces a single item to be emitted by the resulting Observable.

Sasxa
  • 40,334
  • 16
  • 88
  • 102
7

Use forkJoin, which is equivalent to $q.all from Angular 1.x (a and b are observables):

Rx.Observable.forkJoin([a,b]).subscribe(t=> {
        var firstResult = t[0];
        var secondResult = t[1];
});
Community
  • 1
  • 1
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
5

complete is executed when all the source stream are closed.

Rx.Observable.merge(
  myService.upload('upload1'),
  myService.upload('upload2').subscribe({complete: () => { ... });

if you want to set a max number of results to wait for

Rx.Observable.merge(
  myService.upload('upload1'),
  myService.upload('upload2')
.take(2)
.subscribe({complete: () => { ... });
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • But got an error message: ***ORIGINAL EXCEPTION: ReferenceError: Can't find variable: Rx*** – Bagusflyer Feb 16 '16 at 04:57
  • Should be something like this: ***myService1.merge(myService2).subscribe()***. But this is not what I want. What I want is to get the last event. – Bagusflyer Feb 16 '16 at 06:08
  • Do you need the last event, or do you just want to know when the last event has happened, that's what `complete` is for (works only if the source observables are closed by the sender after the event) – Günter Zöchbauer Feb 16 '16 at 06:10
  • Yes, I see. That helps (I call **complete()** to close in sender). Thanks – Bagusflyer Feb 16 '16 at 10:00
2

You can use Promise.all which returns a new Promise that resolves when all of the promises in the argument array have resolved.

Promise.all([myService.upload('upload1'), myService.upload('upload2')]).then(() => {
  // ...
});

Note, if your myService.upload method returned a Promise, rather than Promise, you could access the return values this way:

Promise.all([myService.upload('upload1'), myService.upload('upload2')])
  .then((retValue1, retValue2) => {
  // ...
});
Felix Livni
  • 1,164
  • 13
  • 24