web-dev-qa-db-fra.com

TypeScript - attend un observable / promesse pour terminer et retourne observable

Je suis assez nouveau dans TypeScript & RxJS et j'essaie de renvoyer un Observable après un autre Observable est terminé:

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');
        });

}

J'ai reçu cette erreur: "L'abonnement de type d'expression renvoyé n'est pas assignable au type Observable<any> ".

Je comprends tout à fait l’erreur ici (Un Observable est comme un flux, et un abonnement est le fait de "observer" ce flux), mais je ne vois pas comment "attendre" un Observable(ou une promesse) pour finir de retourner un nouveau Observable. Comment puis je faire ça?

29
Geoffrey D

Le problème est que nous convertissons observable en types différents ... avec .subscribe - alors que nous ne devrions pas (il ne retourne pas observable)

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

Quand nous avons un observable ... nous devrions simplement prendre son résultat et utiliser .map pour le convertir en autre chose

FlatMap opérateur

transformer les éléments émis par un observable en observables, puis en aplatir les émissions en un seul 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();
              })
              ...

Vérifiez tous les détails ici

PROFITANT DES OBSERVABLES DANS ANGULAR 2

23
Radim Köhler

Alors que flatMap () peut fonctionner, puisque vous ne transmettez pas un paramètre utilisé [voir param (x)], le meilleur opérateur à utiliser dans ce scénario est forkJoin ().

Veuillez voir cet exemple: 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

Je cherche cette réponse quelques jours parce que c'est aussi mon problème. Aujourd'hui, j'ai la réponse et j'aimerais partager.

Le code est:

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(); }
  );**
}

et la fonction terminée sera exécutée une fois l'abonnement terminé.

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; });
}

J'espère que cela t'aides.

0