Как бы вы вернули Observable <T>из функции - PullRequest
0 голосов
/ 15 января 2019

У меня есть эта функция:

  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 со всеми свойствами, присвоенными ей внутри функции. Как бы Вы это сделали?

Если я просто верну data, это не работает, так как this.getClientData() и this.otherData() еще не завершено.

1 Ответ

0 голосов
/ 15 января 2019

Ну, у вас есть несколько вопросов / проблем здесь. Начну с самого простого. Как вы получаете наблюдаемое от функции / объекта? Ответ через наблюдаемый из :

return of(data);

Но вы избежали более масштабной проблемы, а именно: как отложить возврат данных до тех пор, пока наблюдаемые дочерние объекты не передадут свои значения? Вы ищете forkJoin . Через документы:

forkJoin будет ожидать завершения всех переданных наблюдаемых, а затем будет выдавать массив с последними значениями из соответствующих наблюдаемых. Поэтому, если вы передадите n Observables оператору, результирующий массив будет иметь значения n, где first value - это последнее, что испускается первым Observable, второе значение - это последнее, что испускается вторым Observable, и так далее. Это означает, что forkJoin не будет излучать более одного раза и завершится после этого.

У вас также есть несколько других проблем. Например, вы никогда не подписываетесь на this.getClientData() или this.otherData(). Наблюдаемые объекты лениво исполняются. Код в вашей наблюдаемой не будет выполняться, пока что-то не подпишется на него. От документов :

Код внутри Observable.create(function subscribe(observer) {...}) представляет «Наблюдаемое выполнение», ленивое вычисление, которое происходит только для каждого Наблюдателя, который подписывается .

Это также выглядит так, как будто вы используете pipe/map в попытке установить свойство для вашего data объекта. Но вы никогда не устанавливаете data.client или data.other, поэтому они всегда будут пустыми.

Итак, собрав все воедино, вы увидите, как может выглядеть ваш код с симулированной задержкой сервера, чтобы показать, что forkJoin ожидает завершения обеих наблюдаемых:

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() и подпишитесь на наблюдаемую , вы увидите, что forkJoin работает, как предполагалось, и нам нужно подождать 2 секунды, пока обе дочерние наблюдаемые завершатся, а наша наблюдаемая излучит значение:

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

Похоже, вы новичок в RxJS / асинхронном программировании. Я предлагаю прочитать отличное введение в RxJs, когда у вас есть шанс. Сначала это может быть сложно, но с практикой это станет второй натурой.

...