admin管理员组

文章数量:1327661

I have few Observables like this one in my code.

this.server.doRequest().subscribe(response => console.log(response)
      error => console.log(error),
      () => {
        console.log('pleted');
      });

There could be any number of these Observables, so I need to write a function that checks if each Observable is done otherwise waits till each is finished.

I'm assuming I can create an array push every new Observable there and when it's pleted remove it by index. But is it good solution?

Where I want to use it. For example I have a page where user upload photos any amount asynchronously and then he press Finish button. Once he pressed Finish button I need to wait till ALL dynamically created Observables are pleted.

I have few Observables like this one in my code.

this.server.doRequest().subscribe(response => console.log(response)
      error => console.log(error),
      () => {
        console.log('pleted');
      });

There could be any number of these Observables, so I need to write a function that checks if each Observable is done otherwise waits till each is finished.

I'm assuming I can create an array push every new Observable there and when it's pleted remove it by index. But is it good solution?

Where I want to use it. For example I have a page where user upload photos any amount asynchronously and then he press Finish button. Once he pressed Finish button I need to wait till ALL dynamically created Observables are pleted.

Share Improve this question edited Jun 10, 2020 at 6:26 Paul Rooney 21.6k9 gold badges44 silver badges62 bronze badges asked Jul 13, 2019 at 14:02 NickDNickD 691 silver badge7 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 5

you should use higher order observables for this, your exact use case will dictate the exact operator, but forkJoin seems a good candidate:

forkJoin(
  this.server.doRequest1(),
  this.server.doRequest2(),
  this.server.doRequest3(),
  this.server.doRequest4()
).subscribe(vals => console.log('all values', vals));

forkJoin won't emit till all innter observables have pleted. making it the operator of choice for waiting for multiple observables to plete. You can also feed it an array of observables. There are multiple other operators that may fulfill your case too, such as concat, merge, bineLatest or a few others.

edit based on more details:

in the use case described in your update, you'll still want to use a higher order observable, but forkjoin is not what you want. you'll want to use a local subject to acplish the goal as wanting to kick off each observable as it is selected and waiting for them all to be done plicates things a little (but not too much):

suppose you had a template like:

<button (click)="addPhoto()">Add Photo</button>

<button (click)="finish()">Finish</button>

where the add photo button gets the users photo and all that, and finish is your pletion, you could have a ponent like this:

private addPhoto$ = new Subject();

constructor() {
  this.addPhoto$.pipe(
    mergeMap(() => this.uploadPhoto()),
  ).subscribe(
    (resp) => console.log('resp', resp),
    (err) => console.log('err', err),
    () => console.log('plete')
  );
}

private uploadPhoto() {
  // stub to simulate upload
  return timer(3000);
}

addPhoto() {
  this.addPhoto$.next();
}

finish() {
  this.addPhoto$.plete();
}

if you run this code, you'll see that the photo adds will emit in the subscribe handler as they plete, but plete will only fire once all the photo uploads have pleted and the user has clicked finish.

here is a stackblitz demonstrating the functionality:

https://stackblitz./edit/angular-bsn6pz

I'd create a dictionary (in javascript that would be a JSON with observable names as boolean properties) where you push each observable on "create" and a method which should execute on pletion of each observable, which will iterate through that dictionary and if all pleted do something. That will ensure parallelism and final execution after all pleted.

var requests = {
    doRequest1: false,
    doRequest2: false,
    doRequest3: false
};

var checkIfCAllCompleted = name => {
    requests[name] = true;
    for (var property in requests) {
        if (object.hasOwnProperty(property)) {
            if (!property) {
                return;
            }
        }
    }
    // all properties are true - do something here
    console.log("here");
}
this.server.doRequest1().then(() => checkIfCAllCompleted("doRequest1"));
this.server.doRequest2().then(() => checkIfCAllCompleted("doRequest2"));
this.server.doRequest3().then(() => checkIfCAllCompleted("doRequest3"));

本文标签: javascriptWait till all Observables are completedStack Overflow