Результат forkJoin с картой в исходном коде

#typescript #rxjs #observable

#typescript #rxjs #наблюдаемый

Вопрос:

Я пытаюсь использовать forkJoin для получения результатов нескольких наблюдаемых (http-запросов в реальном коде) вместе.

К одному из исходных наблюдаемых ( mainObs ниже) map применен оператор, чтобы выходные данные имели тот же формат, что и другие наблюдаемые.

Моя проблема в том, что в forkJoin subscribe первый результат является наблюдаемым, а не выводом первого наблюдаемого.

Вот пример кода с демонстрацией stackblitz.

Я что-то упустил?

 import { forkJoin, Observable, of } from 'rxjs'; 
import { map } from 'rxjs/operators';

let mainObs = of("main").pipe(map(res => of({success: true, result: res})));

let listOfObservables: Observable<any>[] = [mainObs];

listOfObservables.push(createObs());
listOfObservables.push(createObs());

forkJoin(listOfObservables).subscribe((res: any[]) => {
      console.log(res);
      //Problem: res[0] is an Observable, not a value
      console.log(res[0].success);// <==error
      
    });
    

function createObs()
{
  return of({success: true, result: "dummy"})
}
 

Комментарии:

1. Используйте subscribe на res[0].подписаться

Ответ №1:

of создает новую наблюдаемую. Таким образом, вы mainObs возвращаете новую наблюдаемую, когда она возвращается.

Вероятно, вы хотели вернуть фактический результат:

 import { forkJoin, Observable, of } from "rxjs";
import { map } from "rxjs/operators";

let mainObs = of("main").pipe(map(res => ({ success: true, result: res })));

// creating a typed array helps preventing this problem early.
let listOfObservables: Observable<{ success: boolean; result: string }>[] = [
  mainObs
];

listOfObservables.push(createObs());
listOfObservables.push(createObs());

forkJoin(listOfObservables).subscribe(
  (res: { success: boolean; result: string }[]) => {
    console.log(res);
    console.log(res[0].success); // <== ok
  }
);

function createObs() {
  return of({ success: true, result: "dummy" });
}
 

Пример StackBlitz

Ответ №2:

1: map

 of("main").pipe(
  map(res => of({success: true, result: res}))
);
 

Это принимает строку «main», а затем сопоставляет эту строку с наблюдаемой. Это наблюдаемое излучается. То, что делает это наблюдаемое, здесь не имеет значения, поскольку на него никогда не подписывались.

2: mergeMap

 of("main").pipe(
  mergeMap(res => of({success: true, result: res}))
);
 

Это принимает строку «main», а затем сопоставляет эту строку с наблюдаемой. На возвращаемый наблюдаемый объект подписывается, и его выбросы передаются вперед. Наконец, {success: true, result: "main"} выдается.

3: Вернуться к map

 of("main").pipe(
  map(res => ({success: true, result: res}))
);
 

Это принимает строку «main» и сопоставляет ее с объектом {success: true, result: "main"} . Затем этот объект генерируется.


# 2 и # 3 имеют одинаковый конечный результат в этих примерах. Как и в большинстве задач, обычно существует несколько способов достижения одного и того же результата. # 3 является наиболее эффективным в этом случае, поскольку вы избегаете создания наблюдаемого и управления им с помощью mergeMap.