angular - Använd RxJs Pipe för att reducera Observable till en annan typ
Jag har en Observable<Recipe[]> som jag vill reducera till en array av en annan klass ChartData[] för att använda som datakälla för en highcharts-graf (kolumn- och pajdiagram).
Jag försöker använda RxJS pipe-operatören på Observable<Recipe[]> för att kalla på reduce-operatören på mina data men jag kan inte få det att fungera? reduce-operatören itererar inte över objekten i min Observable<Recipe[]> Nedan är mitt försök:
this.foodService.getAllReceipes()
.pipe(
reduce((array: ChartData[], value: Recipe[], i: number) => {
const author = this.createOrFindAuthor(array, value[i]);
author.y += 1;
return array;
}, new Array<ChartData>())
)
.subscribe(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)));
}
getAllRecipes() returnerar Observable<Recipe[]>
this.chartData$ är Observable<ChartData[]>
Jag försöker reducera detta till ChartData[]. Jag har kunnat göra detta i subscribe-operatorn och diagrammen visar de förväntade uppgifterna, men jag trodde att jag borde kunna göra det som en pipebar operator? Här är reduktionen som görs som en del av subscriben:
this.foodService.getAllReceipes()
.subscribe((data) => {
const list = data.reduce((arr: ChartData[], v: Recipe) => {
const author = this.createOrFindAuthor(arr, v);
author.y += 1;
return arr;
}, new Array<ChartData>());
this.chartData$ = of(list.sort((a, b) => b.y - a.y));
});
Jag har försökt använda subscribe-koden inom den rörbara reduce men jag får kompileringsfel som säger att metoden förväntar sig Recipe[] för värdet. Men om jag använder arrayen får jag bara det första elementet från Observable (eller får jag bara Observable och behöver göra något med det?)
Är detta möjligt eller är mitt tankesätt fel om hur den pipbara operatorn ska fungera på Observable?
Som referens här är modellerna och funktionen createOrFindAuthor:
export class Recipe {
public Title: string;
public Author: string;
public Source: string;
public Page: number;
public Link?: string;
}
export class ChartData {
name: string;
y: number;
}
private createOrFindAuthor(array: ChartData[], recipe: Recipe): ChartData {
const name = (recipe.Author.length > 0 ? recipe.Author : 'UNKNOWN');
let found = array.find(i => i.name === name);
if (!found) {
const newData = new ChartData();
newData.name = name;
newData.y = 0;
array.push(newData);
found = newData;
}
return found;
}
Svar #1
Så Chau Tran satte mig på rätt spår. Tydligen behövde jag switchMap Observable till en Recipe[] och reduce-operatorn var då glad att acceptera en Recipe som värde. Lösningen är som följer:
this.foodService.getAllReceipes()
.pipe(
switchMap(data => data as Recipe[]), <<== ADDED THIS
reduce((array: ChartData[], value: Recipe) => {
const author = this.createOrFindAuthor(array, value);
author.y += 1;
return array;
}, new Array<ChartData>()),
switchMap(data => this.chartData$ = of(data.sort((a, b) => b.y - a.y)))
)
.subscribe();
Svar #2
Efter reduce, försök:
switchMap(data => {
this.chartData$ = of(data.sort((a, b) => b.y - a.y));
return this.chartData$;
})
.subscribe()
