angular - 使用 concatMap 从链式 HTTP 调用返回 Observables
问题描述
在 Angular 9 服务类中,我使用 RxJS 链接了几个 HTTP 调用concatMap
,使用第一个调用的输出作为第二个调用的输入:
getUserDetails(authorisationCode: string): Observable<UserInfo> {
this.getAuthorisationTokens(authorisationCode)
.pipe(
concatMap(authorisationTokens => this.getUserInfo(authorisationTokens.access_token)))
.subscribe(
(data: UserInfo) => {
this.userInfo = data;
console.log(JSON.stringify(this.userInfo));
console.log(JSON.stringify(data));
},
(err: any) => console.log('Error getting user info details : ' + err),
() => {
console.log('Got user information: ' + this.userInfo);
}
);
return of(this.userInfo);
}
我想返回this.userInfo
给调用者,我的第一个天真的想法是将它包装在 Observable ( return of(this.userInfo)
) 中并像这样调用它:
export class LandingComponent implements OnInit {
username: string;
userFirstName: string;
email: string;
constructor(private route: ActivatedRoute, private userService: UserDataService) {
this.authorisationCode = route.snapshot.queryParamMap.get('code');
console.log('Code was ' + this.authorisationCode);
}
ngOnInit(): void {
this.userService.getUserDetails(this.authorisationCode)
.subscribe((data: UserInfo) => {
this.userFirstName = data.given_name;
this.username = data.preferred_username;
this.email = data.email;
console.log('Got: ' + this.userFirstName + ', ' + this.username + ', ' + this.email);
});
}
}
我可以从浏览器控制台看到对我的服务的调用正在成功并填充我的 object this.userInfo
,但只有在我尝试使用它并得到一个未定义的错误之后:
Code was 2ffa40f9-5e71-4f29-8ddd-318e8d0b99bc
main-es2015.8df8d853b157ca70b40a.js:1 Getting authorisation tokens in exchange for authorisation code 2ffa40f9-5e71-4f29-8ddd-318e8d0b99bc
main-es2015.8df8d853b157ca70b40a.js:1 Header: [object Object]
main-es2015.8df8d853b157ca70b40a.js:1 Body: grant_type=authorization_code&redirect_uri=https://xxx/landing/&client_id=xxx&code=2ffa40f9-5e71-4f29-8ddd-318e8d0b99bc&client_secret=xxx
main-es2015.8df8d853b157ca70b40a.js:1 TOKEN endpoint: https://xxx.amazoncognito.com/oauth2/token
TOKEN endpoint: https://xxx.amazoncognito.com/oauth2/token
main-es2015.8df8d853b157ca70b40a.js:1 ERROR TypeError: Cannot read property 'given_name' of undefined
...
USERINFO endpoint https://xxx.amazoncognito.com/oauth2/userInfo
main-es2015.8df8d853b157ca70b40a.js:1 USERINFO endpoint https://xxx.amazoncognito.com/oauth2/userInfo
main-es2015.8df8d853b157ca70b40a.js:1 {"sub":"4bfd88a4-5439-4ad6-a399-71b02034dfa1","email_verified":"true","given_name":"Craig","family_name":"Caulfield","email":"craig.caulfield@xxx.com","username":"4bfd88a4-5439-4ad6-a399-xxx"}
main-es2015.8df8d853b157ca70b40a.js:1 Got user information: [object Object]
我试图应用以下问题,但我找不到将它们应用于我的案例的方法:
所以,我的异步想法是错误的。有什么我没有做过的明显的事情吗?
解决方案
您可能会返回undefined
,因为this.userInfo
它是异步赋值的。一种正确的方法是返回 HTTP observable 并在控制器中订阅它。
我也已经将提取authorisationCode
从钩子constructor
移到了ngOnInit()
钩子上。虽然通常ngOnInit()
钩子会在constructor
调用之后触发,但不能保证在触发钩子时变量this.authorisationCode
已经被赋值。
尝试以下
服务
getUserDetails(authorisationCode: string): Observable<any> {
return this.getAuthorisationTokens(authorisationCode)
.pipe(
concatMap(authorisationTokens => this.getUserInfo(authorisationTokens.access_token))
);
}
控制器
constructor(private route: ActivatedRoute, private userService: UserDataService) { }
ngOnInit(): void {
const authorisationCode = route.snapshot.queryParamMap.get('code');
this.userService.getUserDetails(authorisationCode).subscribe(
(data: UserInfo) => {
this.userFirstName = data.given_name;
this.username = data.preferred_username;
this.email = data.email;
console.log('Got: ' + this.userFirstName + ', ' + this.username + ', ' + this.email);
},
(err: any) => { console.log('Error getting user info details : ' + err) },
() => { console.log('Got user information: ' + data); }
);
}
推荐阅读
- python - 圆柱对称磁场
- go - go-runtime 不会将对象推出缓冲通道
- r - 如果满足条件,则从前一行添加值,否则从同一行但不同列添加值
- java - Mockito @Spy 在相同类型的字段上
- linux - 变量/文件中的特殊字符问题。相同的字符串,不同来源的不同格式
- echarts - 我们可以在 eChart 热图工具提示中重复一个字符串模板吗?
- mysql - 无法在 raspian 上连接到 MySQL
- postman - TypeError:无法读取未定义的属性“Slug””
- jquery - jQuery平滑滚动在iOS Safari上奇怪地工作
- openmodelica - 基于 OpenModelica Fortran 的外部函数读\写错误