web-dev-qa-db-de.com

TypeScript - Warten Sie, bis ein Observable / Promise beendet ist, und geben Sie Observable zurück

Ich bin ein Neuling in TypeScript & RxJS und versuche, einen Observable zurückzugeben, nachdem ein anderer Observable fertig ist:

public myObservable = () : Observable<boolean> => {
    console.log('retrieving the token in DB');
    return Observable.create(observer => {
        setTimeout(() => {
            observer.next(true);
            observer.complete();
        }, 5000);
    });
}

public makeRequest = (): Observable<any> => {
    return this.myObservable().subscribe(
        function (x) {
            console.log('I have the token, now I can make the HTTP call');

            return this.http.get('http://jsonplaceholder.typicode.com/posts/1')
                .map( (responseData) => {
                    return responseData.json();
                })
                .map((item:any) => {
                    return {
                        id: item.id,
                        userId: item.userId,
                        title: item.title,
                        body: item.body
                    };
                });

        },
        function (err) {
            console.error('Error: ' + err);
        },
        function () {
            console.log('Completed');
        });

}

Ich habe folgende Fehlermeldung erhalten: "Das Abonnement für den zurückgegebenen Ausdruckstyp kann nicht dem Typ Observable<any> Zugewiesen werden.".

Ich verstehe den Fehler hier völlig (ein Observable ist wie ein Stream, und ein Abonnement ist die Tatsache, dass dieser Stream "beobachtet" wird, aber ich verstehe nicht, wie man auf einen Observable "wartet" - (oder ein Versprechen) um das Zurückgeben einer neuen Observable zu beenden. Wie kann ich das machen?

29
Geoffrey D

Das Problem ist, dass wir Observable in einen anderen Typ konvertieren ... mit .subscribe - während wir nicht sollten (es kommt nicht beobachtbar zurück)

public makeRequest = (): Observable<any> => {
    return this.myObservable().subscribe(
      ... // this is wrong, we cannot return .subscribe
          // because it consumes observable and returns ISusbcriber
    );
}

Wenn wir eine beobachtbare Datei haben ... sollten wir einfach ihr Ergebnis nehmen und .map verwenden, um sie in etwas anderes zu konvertieren

FlatMap operator

wandeln Sie die von einem Observable ausgegebenen Elemente in Observables um und reduzieren Sie dann die Emissionen von diesen in ein einzelnes Observable

public makeRequest = (): Observable<any> => {
    return this.myObservable()
       .flatmap((x) => return this.http
              .get('http://jsonplaceholder.typicode.com/posts/1')
              .map( (responseData) => {
                    return responseData.json();
              })
              ...

Überprüfen Sie alle Details hier

DIE VORTEILE VON OBSERVABLES IN ANGULAR 2

23
Radim Köhler

Während flatMap () möglicherweise funktioniert, da Sie keinen verwendeten Parameter übergeben [siehe param (x)], ist forkJoin () der beste Operator für dieses Szenario.

Beachten Sie dieses Beispiel: https://stackoverflow.com/a/38049268/174239

   Observable.forkJoin(
    this.http.get('/app/books.json').map((res:Response) => res.json()),
    this.http.get('/app/movies.json').map((res:Response) => res.json())
).subscribe(
  data => {
    this.books = data[0]
    this.movies = data[1]
  },
  err => console.error(err)
);
14
rbj325

Ich suche einige Tage nach dieser Antwort, weil dies auch mein Problem ist. Heute habe ich die Antwort und möchte teilen.

Der Code lautet:

ngOnInit() {
var idEntidade: number;

this.route.paramMap.subscribe(params => {
  idEntidade = Number(params.get('id'));
});

this.dataService.getEstados().subscribe(data => {
  this.estados = data;
});

var dados = this.dataService.getCliente(idEntidade);

**this.subscription = dados.subscribe(
  (data: Cliente) => { this.entityForm.patchValue(data);},
  null,
  () => { this.completed(); }
  );**
}

und die abgeschlossene Funktion wird ausgeführt, nachdem das Abonnement abgeschlossen ist.

completed(){
let idEstado: number = this.entityForm.controls['estadoId'].value;

if (idEstado === null) {
  return;
}

this.dataService.getMunicipiosByEstado(this.entityForm.controls['estadoId'].value)
    .subscribe(data => { this.municipios = data; });
}

Hoffe das hilft.