TypeScript - 等待 observable/promise 完成,然后返回 observable

Posted

技术标签:

【中文标题】TypeScript - 等待 observable/promise 完成,然后返回 observable【英文标题】:TypeScript - wait for an observable/promise to finish, and return 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 个内部可观察对象。 【参考方案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://***.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

【讨论】:

平面图/合并图示例:stackblitz.com/edit/angular-mergemap

以上是关于TypeScript - 等待 observable/promise 完成,然后返回 observable的主要内容,如果未能解决你的问题,请参考以下文章

html 使用AJAX POST请求来调用控制器操作(在页面加载时和在下拉列表中选择项目时),获取返回的布尔值,设置observabl

如何等待 JavaScript/TypeScript 中的 Promise 列表?

typescript 等待

typescript 异步/等待

在TypeScript中等待Foreach给出错误

如何在 Vscode 中的 Typescript 中等待后调试代码?