我有一个应用程序应该return menu based on given context
.
下面是menuA
和menuB
的来源。
// 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
的知识和经验有限,我希望下面的代码片段可以接受menuA
或menuB
的string
来返回required menu
的observable
:
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 12
和rxjs "~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);
});
}
}