选择性地返回forkJoin



我有一个应用程序应该return menu based on given context.

下面是menuAmenuB的来源。

// example of menu derived from given source
menuA() {
return [
{
a: 'demo1',
b: 'demo2',
c: 'demo3'
},
{
e: 'demo4',
f: 'demo5',
g: 'demo6'
}
];
}
// example of menu fetched from different source eg: db
async menuB() {
const ret = [];
const h = {
a: 'demo1',
b: 'demo2',
c: 'demo3'
};
ret.push(h);
return await ret;
}

鉴于我对rxjs的知识和经验有限,我希望下面的代码片段可以接受menuAmenuBstring来返回required menuobservable:

getMenu$(context: string) {
return forkJoin(
{
menuA: of(this.menuA()),
menuB: from(this.menuB())
}
).pipe(
mergeMap((m: any) => {
return m[context];
})
)
}

上面调用的警告如下:

Argument of type 'Observable<unknown>' is not assignable to parameter of type 'OperatorFunction<{ menuA: ({ a: string; b: string; c: string; e?: undefined; f?: undefined; g?: undefined; } | { e: string; f: string; g: string; a?: undefined; b?: undefined; c?: undefined; })[]; menuB: { a: string; b: string; c: string; }[]; }, unknown>'.
Type 'Observable<unknown>' provides no match for the signature '(source: Observable<{ menuA: ({ a: string; b: string; c: string; e?: undefined; f?: undefined; g?: undefined; } | { e: string; f: string; g: string; a?: undefined; b?: undefined; c?: undefined; })[]; menuB: { a: string; b: string; c: string; }[]; }>): Observable<...>'.ts(2345)
The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<any>'.ts(2684)

根据下面的注释,我还添加了当使用map来替换mergeMap时的警告消息:

// modified getMenu$:
getMenu$(context: string) {
return forkJoin(
{
menuA: of(this.menuA()),
menuB: from(this.menuB())
}
).pipe(
map(m => m[context])
)
}

警告消息:

Argument of type 'Observable<unknown>' is not assignable to parameter of type 'OperatorFunction<{ menuA: ({ a: string; b: string; c: string; e?: undefined; f?: undefined; g?: undefined; } | { e: string; f: string; g: string; a?: undefined; b?: undefined; c?: undefined; })[]; menuB: { a: string; b: string; c: string; }[]; }, unknown>'.
Type 'Observable<unknown>' provides no match for the signature '(source: Observable<{ menuA: ({ a: string; b: string; c: string; e?: undefined; f?: undefined; g?: undefined; } | { e: string; f: string; g: string; a?: undefined; b?: undefined; c?: undefined; })[]; menuB: { a: string; b: string; c: string; }[]; }>): Observable<...>'.ts(2345)
The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<unknown>'.ts(2684)

我使用angular 12rxjs "~6.6.0"

DEMO: https://stackblitz.com/edit/typescript-ktm2hz?file=index.ts

function menuA() {
return [
{
a: 'demo1',
b: 'demo2',
c: 'demo3'
},
{
e: 'demo4',
f: 'demo5',
g: 'demo6'
}
];
}

// example of menu fetched from different source eg: db
function menuB() {
return of([
{
a: 'demo1',
b: 'demo2',
c: 'demo3'
}
]).pipe(delay(500));
}

function getMenu$(context: string) {
return forkJoin(of(menuA()), menuB().pipe(first())).pipe(
map(([menuA, menuB]) => ({ menuA, menuB })),
map(m => m[context])
);
}
getMenu$('menuA').subscribe(data => {
console.log(data);
});
getMenu$('menuB').subscribe(data => {
console.log(data);
});

更新:

你需要声明菜单。我已经为它创建了Enum

用Angular 12演示:https://stackblitz.com/edit/angular-12-template-wcgohi?file=src/app/app.component.ts

import { Component, OnInit } from '@angular/core';
import { forkJoin, Observable, of } from 'rxjs';
import { first, map, delay } from 'rxjs/operators';
enum Menus {
menuA = 'menuA',
menuB = 'menuB'
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
menuA(): { [key: string]: any }[] {
return [
{
a: 'demo1',
b: 'demo2',
c: 'demo3'
},
{
e: 'demo4',
f: 'demo5',
g: 'demo6'
}
];
}
// example of menu fetched from different source eg: db
menuB(): Observable<{ [key: string]: any }[]> {
return of([
{
a: 'demo1',
b: 'demo2',
c: 'demo3'
}
]).pipe(delay(500));
}
getMenu$(context: Menus): Observable<{ [key: string]: any }[]> {
return forkJoin([of(this.menuA()), this.menuB().pipe(first())]).pipe(
map(([menuA, menuB]) => ({ menuA, menuB })),
map(m => m[context])
);
}
ngOnInit() {
this.getMenu$(Menus.menuA).subscribe(data => {
console.log(data);
});
this.getMenu$(Menus.menuB).subscribe(data => {
console.log(data);
});
}
}

最新更新