如何在 rxjs Angular 中使用管道内的两个 concatmap 时在订阅块内提取结果
How to extract result inside subscribe block while using two concatmap inside pipe in rxjs Angular
我有如下代码:
this.security.isLoggedIn$
.pipe(
distinctUntilChanged(),
switchMap(
(isLoggedInApp: boolean) =>
isLoggedInApp
? of(true).pipe(
concatMap(() => this.security.getUser()),
concatMap(( partyId ) => this.loginService.getLendingType(partyId))
)
: of(false).pipe(finalize(() => this.router.navigateByUrl('login'))) //// TODO: needs refactoring, investigate routing
)
)
.subscribe((result) => {
console.log(result);
//this log prints {"lendingType": "LendingPartner","partyId": "64f9f398-3a79-48d6-b4b7-89d41ccedb3b"}
});
在上面的代码中,我的问题是,我想访问调用 getLendingType(partyId) 的结果。这是我的 getLendingType(partyId)
代码
public getLendingType(partyId: string): Observable<{ lendingType: string, partyId: string }> {
return this.customerService.getCustomer(partyId).pipe(
map((customer: ICustomer) => {
return { lendingType: customer.LendingType, partyId: partyId } ;
})
);
}
所以 getLendingType 返回两个值。所以这里的问题是,我无法在订阅块中访问这两个值。但是,当我只返回一个值(例如 lendingType)时,我可以在订阅块中访问它。具体来说,我实际上在订阅块中获取了这两个值,正如您在日志打印中看到的那样。但是我不知道如何访问它们。如果我将鼠标悬停在可视代码中的结果上,它会显示结果由一个布尔值和一个对象组成,如下图所示。
我已经尝试了 result.lendingType 或结果 ['lendingType'],这会给我带来编译器错误,因为结果是一个复杂的对象,如图所示。在这种情况下,访问这两个值的方式是什么。
提前致谢。
您可以构建这样的类型检查:
if (typeof result !== "boolean"){
console.log(result.lendingType)
}
Typescript 现在足够聪明,可以知道 result
不再是 boolean
类型。
您创建的管道 returns 如果用户已登录,则为 LendingData,如果用户未登录,则为布尔值 (false)。这就是为什么当您尝试访问 result.lendingType
或 result['lendingType']
在失败案例 (!isLoggedInApp) 上,您的代码尝试执行以下操作:false.lendingType
。这是不正确的,因此会引发错误。
如果您曾经对自己编写的管道感到困惑,我建议您通过拆分来简化它。这是很好的做法,您的同事稍后会感谢您。在这种情况下,在两个不同的管道中处理 LendingData 和导航。
/* ----------------- Deal with lending data ---------------- */
private getLendingData$ = this.security.getUser().pipe(
switchMap((partyId) => this.loginService.getLendingType(partyId))
);
public lendingData$ = this.security.isLoggedIn$.pipe(
distinctUntilChanged(),
// if the user is logged in, return their lending data, else return null
switchMap(isLoggedIn => iif(() => isLoggedIn, getLendingData$, of(null)),
// so you don't make the API call more than once
// for multiple subscribers
shareReplay(1)
);
lendingData$.subscribe((result) => {
// can return LendingData or null, therefore, access data with ?.
// Ie) result?.lendingType
console.log(result);
// this log prints
// {
// "lendingType": "LendingPartner",
// "partyId": "64f9f398-3a79-48d6-b4b7-89d41ccedb3b"
// }
});
/* ----------------- Deal with navigation ---------------- */
this.security.isLoggedIn$.pipe(
distinctUntilChanged(),
filter(isLoggedIn => !isLoggedIn)
).subscribe(() => {
this.router.navigateByUrl('login'));
});
我有如下代码:
this.security.isLoggedIn$
.pipe(
distinctUntilChanged(),
switchMap(
(isLoggedInApp: boolean) =>
isLoggedInApp
? of(true).pipe(
concatMap(() => this.security.getUser()),
concatMap(( partyId ) => this.loginService.getLendingType(partyId))
)
: of(false).pipe(finalize(() => this.router.navigateByUrl('login'))) //// TODO: needs refactoring, investigate routing
)
)
.subscribe((result) => {
console.log(result);
//this log prints {"lendingType": "LendingPartner","partyId": "64f9f398-3a79-48d6-b4b7-89d41ccedb3b"}
});
在上面的代码中,我的问题是,我想访问调用 getLendingType(partyId) 的结果。这是我的 getLendingType(partyId)
代码 public getLendingType(partyId: string): Observable<{ lendingType: string, partyId: string }> {
return this.customerService.getCustomer(partyId).pipe(
map((customer: ICustomer) => {
return { lendingType: customer.LendingType, partyId: partyId } ;
})
);
}
所以 getLendingType 返回两个值。所以这里的问题是,我无法在订阅块中访问这两个值。但是,当我只返回一个值(例如 lendingType)时,我可以在订阅块中访问它。具体来说,我实际上在订阅块中获取了这两个值,正如您在日志打印中看到的那样。但是我不知道如何访问它们。如果我将鼠标悬停在可视代码中的结果上,它会显示结果由一个布尔值和一个对象组成,如下图所示。
我已经尝试了 result.lendingType 或结果 ['lendingType'],这会给我带来编译器错误,因为结果是一个复杂的对象,如图所示。在这种情况下,访问这两个值的方式是什么。
提前致谢。
您可以构建这样的类型检查:
if (typeof result !== "boolean"){
console.log(result.lendingType)
}
Typescript 现在足够聪明,可以知道 result
不再是 boolean
类型。
您创建的管道 returns 如果用户已登录,则为 LendingData,如果用户未登录,则为布尔值 (false)。这就是为什么当您尝试访问 result.lendingType
或 result['lendingType']
在失败案例 (!isLoggedInApp) 上,您的代码尝试执行以下操作:false.lendingType
。这是不正确的,因此会引发错误。
如果您曾经对自己编写的管道感到困惑,我建议您通过拆分来简化它。这是很好的做法,您的同事稍后会感谢您。在这种情况下,在两个不同的管道中处理 LendingData 和导航。
/* ----------------- Deal with lending data ---------------- */
private getLendingData$ = this.security.getUser().pipe(
switchMap((partyId) => this.loginService.getLendingType(partyId))
);
public lendingData$ = this.security.isLoggedIn$.pipe(
distinctUntilChanged(),
// if the user is logged in, return their lending data, else return null
switchMap(isLoggedIn => iif(() => isLoggedIn, getLendingData$, of(null)),
// so you don't make the API call more than once
// for multiple subscribers
shareReplay(1)
);
lendingData$.subscribe((result) => {
// can return LendingData or null, therefore, access data with ?.
// Ie) result?.lendingType
console.log(result);
// this log prints
// {
// "lendingType": "LendingPartner",
// "partyId": "64f9f398-3a79-48d6-b4b7-89d41ccedb3b"
// }
});
/* ----------------- Deal with navigation ---------------- */
this.security.isLoggedIn$.pipe(
distinctUntilChanged(),
filter(isLoggedIn => !isLoggedIn)
).subscribe(() => {
this.router.navigateByUrl('login'));
});