2017-05-03 3 views
1

Kennen Sie eine Lösung für mein Problem? Ich brauche eine flexible Folge von abonnierten in einer beobachtbaren wie hier gekapselte:Angular2 benutzerdefinierte Observablen mit einigen sequentiellen abonniert

saveData() { 
    return new Observable((observer) => { 
     let success = true; 

     if(example === true) { 
     this.saveCallbarrings().subscribe((response) => { 
      // this response was ignored from angular 
      success = (response === true); 
     }); 
     } 

     if(example2 === true) { 
     this.saveCallbarrings().subscribe((response) => { 
      // this response was ignored from angular too 
      success = (response === true); 
     }); 
     } 

     // and so on ... in the end I need a result of all responses 
     observer.next(success); 
    }); 
    } 

Am Ende habe ich das Ergebnis dieser „Antwort-Sammlung“ bezeichnet in meiner einreichen Methode:

onSubmit() { 
// Validations and others 
... 
if(this.isNew) { 
     observable = this.create(); 
     } else { 
     observable = this.update(); 
     } 

     return observable.subscribe(success => { 
     if(success == true) { 
      let subscription = this.saveData().subscribe(successFinished => { 
      // And here is the problem, because this var doesnt have the correct response 
      if(successFinished === true) { 
       this.alertService.success('ALERT.success_saved', {value: 'ALERT.success_edit_user', param: {user: this.user.username}}); 
      } 
      }); 

      subscription.unsubscribe(); 
     } 
     }); 

der Haupt Problem ist, dass eckig nicht wartet, bis der "Erfolg" var im ersten Codeblock abonniert ist. Warum und was ist die bessere Lösung für mich?

+0

Sie können nicht warten, bis ein Observable oder eine Versprechung abgeschlossen ist. Sie können es nur abonnieren, um benachrichtigt zu werden, wenn es ein Ereignis abschließt oder ausstrahlt. Können Sie bitte die Methode saveExtendedData Service hinzufügen, da Sie die Änderung dort vornehmen können? –

+0

Entschuldigung, ich habe einen Fehler in meinem zweiten Codeblock. Die Methode "this.saveExtendedData()" sollte "this.saveData()" lauten. – Joeker

+0

in der Datensicherungsmethode statt Wert der Erfolgsvariable zuzuweisen, gebe das Ergebnis zurück –

Antwort

1

1. Frage: Warum funktioniert es nicht?

Weil jedes Abonnement asynchron ist. Wenn Sie this.saveCallbarrings().subscribe(...) tun, kann die Sache innerhalb subscribe jederzeit geschehen (vielleicht nie!), Also fährt das Programm zur nächsten Instruktion fort, die observer.next(success); ist, die den Anfangswert von success hat.

2. Frage: Was ist die beste Lösung für mich?

Rx.Observables haben so many operators, um mit diesem asynchronen Zeug umzugehen. In Ihrem Fall ist der Operator, den Sie benötigen, forkJoin. Mit diesem Operator können Sie ihm ein Array von Streams übergeben, und alle werden abonniert. Wenn alle fertig sind, erhalten Sie ein Array mit jedem der Resuts für jeden Stream. So würde Ihr Code werden:

saveData() { 
    return Rx.Observable.defer(() => { 
     let streams = []; 
     if(example === true) { 
      streams.push(this.saveCallbarrings()); 
     } 
     if(example2 === true) { 
      streams.push(this.saveCallbarrings()); 
     } 

     // And so on 

     return Rx.Observable.forkJoin(streams); 
    }); 
} 

Having said that, ich bin nicht sicher, warum Sie viele Abonnements für die gleichen this.saveCallbarrings() machen, ich denke, es ist nur die Frage einfacher zu machen, als Beispiel.

Auch hier habe ich .defer() statt create. Mit diesem können Sie einfach einen anderen Stream zurückgeben und er wird ihn abonnieren und an die Beobachter weitergeben. Der Unterschied zwischen dem Ausführen von defer und dem Nichtstun (z. B. Einrichten der Streams und Zurückgeben des forkJoin) besteht darin, dass defer keinen Code ausführt, bis jemand ihn abonniert, sodass Sie weniger Nebenwirkungen erhalten.

+0

Vielen Dank. Ihre Lösung funktioniert für mich erfolgreich! – Joeker

Verwandte Themen