TypeScript - 等待一个可观察对象/承诺完成,并返回可观察对象

44

我对TypeScript和RxJS还不是很熟悉,我想在另一个 Observable 完成后返回一个 Observable

我对TypeScript和RxJS还不是很熟悉,我想在另一个 Observable 完成后返回一个 Observable

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

}

我收到了这个错误:“返回的表达式类型 subscription 无法分配给类型 Observable<any>”。

我完全理解这个错误 (一个 Observable 就像是一个流,而订阅是“观察”该流的事实),但我不知道如何“等待”一个 Observable (或一个 promise) 完成后再返回一个新的 Observable。我应该怎么做呢?


很好的提示!我的建议是:在rxjs 5.0.1中似乎没有flatMap()方法。我使用mergeMap()来实现“链式”观察或者说有一个外部和两个内部观察。 - Satria
3个回答

24

问题在于我们使用 .subscribe 将可观察对象转换为不同类型... 但事实上我们不应该这样做(它并不返回可观察对象)

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

当我们有一个可观察对象时,应该只需要获取它的结果并使用 .map 将其转换成其他东西。

FlatMap 操作符

将 Observable 发射的项转换成 Observables,然后将这些 Observables 合并成一个 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();
              })
              ...

在此查看所有详细信息

利用Angular 2中的Observables


flatMap/mergeMap示例:https://stackblitz.com/edit/angular-mergemap - Sunil Kumar

17

虽然flatMap()可能可行,但由于您没有传递使用的参数[参见param (x)],在这种情况下最适合使用的运算符是forkJoin()。

请参考此示例:https://dev59.com/PFoT5IYBdhLWcg3w6isA#38049268

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

返回的数据顺序总是如图所示吗?this.book = data [0],而this.movies = data [1]。 - JWP
1
是的,它直接关联到你传入该方法的 observables 的顺序。 - rbj325

0

我已经寻找这个答案好几天了,因为这也是我的问题。今天我终于找到了答案,想要分享给大家。

代码如下:

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

当订阅完成后,函数completed将被执行。

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

希望这能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接