【问题标题】:TypeScript - wait for an observable/promise to finish, and return observableTypeScript - 等待 observable/promise 完成,然后返回 observable
【发布时间】:2016-09-15 05:00:24
【问题描述】:

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

}

我收到此错误:“返回的表达式类型订阅不可分配给类型 Observable&lt;any&gt;”。

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

【问题讨论】:

  • 很好的提示!我的 2 美分:flatMap() 似乎在 rxjs 5.0.1 中不可用。我使用 mergeMap() 来实现可观察对象的“链”,或者换句话说 - 有一个外部和 2 个内部可观察对象。

标签: typescript rxjs observable


【解决方案1】:

有些日子我正在寻找这个答案,因为这也是我的问题。今天我有了答案,想分享一下。

代码是:

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

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    虽然 flatMap() 可能会起作用,但由于您没有传入使用的参数 [参见 param (x)],因此在这种情况下使用的最佳运算符是 forkJoin()。

    请看这个例子:https://stackoverflow.com/a/38049268/1742393

       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.movi​​es = data[1]
    • 是的,它与传递给方法的可观察对象的顺序直接相关。
    【解决方案3】:

    问题是我们将 observable 转换为不同的类型...使用 .subscribe - 而我们不应该(它不返回 observable)

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

    当我们有一个 observable 时......我们应该只获取它的结果并使用 .map 将其转换为其他东西

    FlatMap operator

    将 Observable 发出的项目转换为 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();
                  })
                  ...
    

    在这里查看所有详细信息

    TAKING ADVANTAGE OF OBSERVABLES IN ANGULAR 2

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2018-08-06
    • 1970-01-01
    • 2021-06-20
    相关资源
    最近更新 更多