代码之家  ›  专栏  ›  技术社区  ›  Sergino

如何从函数返回一个observable<t>

  •  1
  • Sergino  · 技术社区  · 7 年前

    我有这个功能:

      getData(): Observable<ServerResponse> {
        const data = {} as ServerResponse;
    
        data.client = this.getClientData().pipe(
          map(response =>
            response.map(x => {
              return x.data.client;
            }),
          ),
        );
    
        data.otherData = this.otherData().pipe(
          map(response =>
            response.map(x => {
              return this.groupByTimePeriod(x.data.other, 'day', 'week');
            }),
          ),
        );
      }
    

    函数需要返回 data 在函数内部分配给它的所有属性。你会怎么做?

    如果我真的回来 数据 它不能像 this.getClientData() this.otherData() 尚未完成。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Dean    7 年前

    好吧,这里有很多问题。我先从最简单的开始。如何从函数/对象中获得可观察的结果?答案是通过观察 of :

    return of(data);
    

    但您回避了一个更大的问题,即:如何推迟返回的数据,直到儿童可见物发出它们的值?你在找 forkJoin . 通过DOCS:

    forkJoin 将等待所有传递的可观测数据完成,然后它将从相应的可观测数据中发出带有最后一个值的数组。所以如果你通过 n 操作员可观察到的结果数组 n 值,其中第一个值是第一个可观测值发出的最后一个值,第二个值是第二个可观测值发出的最后一个值,依此类推。那意味着 福克林 不会发出超过一次,然后会完成。

    你还有其他几个问题。例如,您从不订阅 this.getClientData() this.otherData() . 可观测的数据被懒散地执行。在有东西订阅它之前,Observable中的代码不会执行。从 the docs :

    内部代码 Observable.create(function subscribe(observer) {...}) 表示“可观察执行”, 只对订阅的每个观察者执行的延迟计算。 .

    它还显示出您正在使用 pipe/map 试图在您的 data 对象。但你永远不会设置 data.client data.other ,所以它们总是空的。

    所以,把它们放在一起,下面是您的代码可能是什么样子的,通过模拟服务器延迟来证明这一点。 福克林 等待两个观测数据完成:

    import { Injectable } from '@angular/core';
    import { Observable, of, forkJoin } from 'rxjs';
    import { delay } from 'rxjs/operators';
    
    @Injectable({
        providedIn: 'root'
    })
    export class TestService {
        getData(): Observable<ServerResponse> {
            const allOperations = forkJoin(
                this.getClientData(),
                this.getOtherData()
            );
    
            const observable = Observable.create(function subscribe(observer) {
                // Wait until all operations have completed
                allOperations.subscribe(([clientData, otherData]) => {
                    const data = new ServerResponse;
                    // Update your ServerReponse with client and other data
                    data.otherdata = otherData.other;
                    data.client = clientData.client;
                    // Now that data is 100% populated, emit to anything subscribed to getData().
                    observer.next(data);
                    observer.complete();
                });
    
            });
            // We return the observable, with the code above to be executed only once it is subscribed to
            return observable;
        }
    
        getClientData() : Observable<any> {
            return of({ client: 'Client 1' });
        }
        getOtherData(): Observable<any> {
            // Fake server latency
            return of({ other: 'Other data that takes a while to return from server...' })
                .pipe(delay(2000));
        }
    }
    
    export class ServerResponse {
        client: string;
        otherdata: string;
    }
    

    如果你打电话 getData() 订阅可观察的 你会看到的 福克林 按预期工作,我们必须等待2秒钟,让儿童可观测数据完成,我们的可观测数据发出一个值:

    this.testService.getData().subscribe(data => {
      console.log(data);
    });
    

    似乎您对RXJS/Asynchronous编程还比较陌生。我建议你阅读 the excellent introduction 当你有机会的时候。起初可能很棘手,但随着实践,这将成为第二天性。