问题描述
我有一个获取通知规则列表的功能。问题是,如果不存在通知规则,则该函数会崩溃。导致问题的行是 response.rules.model.map((rule) => {
返回错误:
ERROR TypeError: 无法读取未定义的属性 'map'
public getNotificationRuleItemsSet(): Observable<any[]> {
const commonTxnList = this.configService.config.Notifications.TransactionTypeRules
.CommonTxnList;
const excludeTxnTypes = this.configService.config.Notifications.TransactionTypeRules
.ExcludeTxnTypes;
const showEffectForTxnTypes = this.configService.config.Notifications.TransactionTypeRules
.ShowEffectForTxnTypes;
return this.getNotificationRules().pipe(
take(1),tap((response: any) => {
if (response.txntypes) {
this.txnTypes = response.txntypes.model;
}
if (response.accounts) {
this.accounts = response.accounts.model;
}
}),switchMap((response: any) => {
return forkJoin([
forkJoin(
response.txntypes.model.map((txntype) => {
let commonIndex = commonTxnList.indexOf(txntype.txntypename);
let excludeIndex = excludeTxnTypes.indexOf(txntype.txntypename);
let showEffectIndex = showEffectForTxnTypes.indexOf(
txntype.txntypename
);
let item: INotificationTxnType = {
id: txntype.id,txntypename: txntype.txntypename,locname: txntype.locname,shortList: commonIndex >= 0 ? true : false,exclude: excludeIndex >= 0 ? true : false,showEffect: showEffectIndex >= 0 ? true : false,};
return of(item);
})
),of(response.accounts.model),forkJoin(
response.rules.model.map((rule) => {
switch (rule.type) {
case NotificationType.Account: {
return this.getoneRuleItem_Account(rule).pipe(take(1));
}
case NotificationType.TxnType: {
return this.getoneRuleItem_TxnType(rule).pipe(take(1));
}
case NotificationType.Currency: {
return this.getoneRuleItem_Currency(rule).pipe(take(1));
}
default: {
return of();
}
}
})
),]);
})
);
}
如果没有返回任何规则,则不需要运行下面的代码部分。有没有办法在这个函数中运行检查,比如if(response.rules.length > 0)
然后只运行这部分代码?
forkJoin(
response.rules.model.map((rule) => {
switch (rule.type) {
case NotificationType.Account: {
return this.getoneRuleItem_Account(rule).pipe(take(1));
}
case NotificationType.TxnType: {
return this.getoneRuleItem_TxnType(rule).pipe(take(1));
}
case NotificationType.Currency: {
return this.getoneRuleItem_Currency(rule).pipe(take(1));
}
default: {
return of();
}
}
})
),
解决方法
您可以使用 RxJS iif
函数。此外,您可以使用 RxJS EMPTY
常量代替 of()
。这样,外部 forkJoin
仍会发出,但您不会在订阅中获得 undefined
。当然,如果您希望订阅中有 undefined
,您可以继续使用 of()
。
试试下面的方法
iif(
() => !!response.rules && !!response.rules.model,// <-- use `forkJoin` only if `response.rules` is defined
forkJoin(
response.rules.model.map((rule) => {
switch (rule.type) {
case NotificationType.Account: {
return this.getOneRuleItem_Account(rule).pipe(take(1));
}
case NotificationType.TxnType: {
return this.getOneRuleItem_TxnType(rule).pipe(take(1));
}
case NotificationType.Currency: {
return this.getOneRuleItem_Currency(rule).pipe(take(1));
}
default: {
return EMPTY;
}
}
})
)
)
我已经包含了两个内部 forkJoin
的条件。
public getNotificationRuleItemsSet(): Observable <any[]> {
...
return this.getNotificationRules().pipe(
take(1),tap((response: any) => {
if (response.txntypes) {
this.txnTypes = response.txntypes.model;
}
if (response.accounts) {
this.accounts = response.accounts.model;
}
}),switchMap((response: any) => {
return forkJoin([
iif(
() => !!response.txntypes && !!response.txntypes.model,forkJoin(
response.txntypes.model.map((txntype) => {
let commonIndex = commonTxnList.indexOf(txntype.txntypename);
let excludeIndex = excludeTxnTypes.indexOf(txntype.txntypename);
let showEffectIndex = showEffectForTxnTypes.indexOf(
txntype.txntypename
);
let item: INotificationTxnType = {
id: txntype.id,txntypename: txntype.txntypename,locname: txntype.locname,shortList: commonIndex >= 0 ? true : false,exclude: excludeIndex >= 0 ? true : false,showEffect: showEffectIndex >= 0 ? true : false,};
return of(item);
})
)
),of (response.accounts.model),iif(
() => !!response.rules && !!response.rules.model,forkJoin(
response.rules.model.map((rule) => {
switch (rule.type) {
case NotificationType.Account: {
return this.getOneRuleItem_Account(rule).pipe(take(1));
}
case NotificationType.TxnType: {
return this.getOneRuleItem_TxnType(rule).pipe(take(1));
}
case NotificationType.Currency: {
return this.getOneRuleItem_Currency(rule).pipe(take(1));
}
default: {
return EMPTY;
}
}
})
)
),]);
})
);
}