我无法订阅 angular 13 中可观察到的 mergeMap
I can not subscribe on mergeMap observable in angular 13
我想实现一个基于 angular 中角色的连接场景。当用户在填写表单(用户名 - 密码)后单击 CONNEXION 按钮时,会调用两个 API url 来提供相同的连接,我正在使用 angular 13 作为前端。在后端,我有两个端点(资源请求 url )来服务连接过程。第一个资源
this.http.post(${environment.baseUrlUserSecurity}/users/login
,
data, Option)
提供用于身份验证的令牌和第二个资源
this.http.get(${environment.baseUrlUserSecurity}/prsnls
,
this.userId)
必须根据令牌中第一个 API 调用提供的 userId 找到用户的角色。用邮递员测试时一切正常。但是我正在努力用 angular 在前端实现连接过程,这是我到目前为止所做的:
//调用 2 API URL 的登录方法
login(data){
const Option ={ headers: new HttpHeaders({'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json',"USER_CODE":data.USER_CODE})};
this.http.post<any>(`${environment.baseUrlUserSecurity}/users/login`, data, Option)
.pipe(
map(value => value[0]))
.subscribe( value => {
this.userId = value.result.userId;
this.http.get(`${environment.baseUrlUserSecurity}/prsnls`, this.userId)
.subscribe( user => {
this.user = user;
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
});
})
}
//按下按钮时的提交动作
onSubmit(){
const data = this.loginForm.getRawValue();
this.submitted = true;
localStorage.setItem('USER_CODE',data.USER_CODE);
this.loading = true;
this.isLoading = true;
of(null)
.pipe(
delay(2000),
first()
)
.subscribe(() => {
this.isLoading = false;
this.authService.login(data).subscribe(
(res:any)=>{
if (res.code==200){
localStorage.setItem('token',res.result.token);
localStorage.setItem("infos", JSON.stringify(res.result.roleIds));
localStorage.setItem("prsl", res.result.userId);
//this.getUserInfos(res.result.userId);
this.router.navigate(['/dashboard']);
}
this.rMessage = '';
},
error => {
this.rMessage = 'bError';
this.loading = false;
}
);
});
}
问题是编辑器说'subscribe()'属性在onsubmit()函数内的类型void上不存在this.authService.login(data).subscribe()
而且我不明白为什么我不能订阅那个 observable。如果有人能提供帮助,我将不胜感激,因为我不知道如何解决这个问题并让编辑器没有错误。提前致谢。
记住:“您的服务 return observables,您订阅组件”
每次您在服务中写“订阅”时,您都在犯错误 (*)
好吧,你需要 return 一个基于另一个的可观察对象,所以你需要使用 switchMap rxjs 运算符。 switchMap 总是挡路
observable1(data).pipe(switchMap(res=>{
//here res is the response of the observable1(data)
//you return another observable based in res
return observable2(res)
})
您的登录
login(data){
const Option ={ headers: new HttpHeaders({'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json',"USER_CODE":data.USER_CODE})};
//see that you "return" an observable
return this.http.post<any>(`${environment.baseUrlUserSecurity}/users/login`, data, Option)
.pipe(
switchMap(value=>{
const userId=value[0].result.userId
return this.http.get(`${environment.baseUrlUserSecurity}/prsnls`, userId)
})
现在您可以订阅了
onSubmit(){
const data = this.loginForm.getRawValue();
this.submitted = true;
this.authService.login(data).subscribe(
(res:any)=>{
if (res.code==200){
localStorage.setItem('token',res.result.token);
localStorage.setItem("infos", JSON.stringify(res.result.roleIds));
localStorage.setItem("prsl", res.result.userId);
//this.getUserInfos(res.result.userId);
this.router.navigate(['/dashboard']);
}
this.rMessage = '';
},
error => {
this.rMessage = 'bError';
this.loading = false;
}
);
});
(*)好吧,你可以在你的服务中加入一些像
subject=new Subject<any>()
getData(){
this.httpClient.get(...).subscribe(res=>{
this.subject.next(res)
})
}
然后您订阅“主题”并调用函数
this.authService.subject.subscribe(res=>{
...
})
this.authService.getData();
但它适用于一些“特殊情况”
Update 有时,我们还需要内部 Observable 的数据,我们还需要使用另一个 rxjs 运算符的第一个 observable 的数据 map
我们可以做到
observable1(data).pipe(switchMap(respose1=>{
return observable2(response1).pipe(map(response=>(
{response1:response1,response2:response2}
)))
})
我们有一个具有两个属性的对象:response1 和 response2
我们也可以使用展开运算符进行映射
observable1(data).pipe(switchMap(respose1=>{
return observable2(response1).pipe(map(response=>(
{...response1,...response2}
)))
})
然后我们得到一个具有 response1 和 response2 的所有属性的唯一对象
您需要 return Observable
从 login 方法。
如果您订阅并且 return 那么将会 returning Subcription
type.So in-order 到 return Observable
并且操作结果并在响应出现后做一些事情你必须使用 pipe
.
我改变了你的登录方法如下
login(data): Observable<any> {
const Option = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
USER_CODE: data.USER_CODE,
}),
};
return this.http
.post<any>('${environment.baseUrlUserSecurity}/users/login', data, Option)
.pipe(
map((value) => value[0]),
tap((value) => (this.userId = value.result.userId)),
switchMap((value) =>
this.http
.get<User>('${environment.baseUrlUserSecurity}/prsnls', this.userId)
.pipe(
tap((user:User) => {
this.user = user;
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
}),
map((user) => ({ ...user, ...value }))
)
)
);
}
我想实现一个基于 angular 中角色的连接场景。当用户在填写表单(用户名 - 密码)后单击 CONNEXION 按钮时,会调用两个 API url 来提供相同的连接,我正在使用 angular 13 作为前端。在后端,我有两个端点(资源请求 url )来服务连接过程。第一个资源
this.http.post(
${environment.baseUrlUserSecurity}/users/login
, data, Option)
提供用于身份验证的令牌和第二个资源
this.http.get(
${environment.baseUrlUserSecurity}/prsnls
, this.userId)
必须根据令牌中第一个 API 调用提供的 userId 找到用户的角色。用邮递员测试时一切正常。但是我正在努力用 angular 在前端实现连接过程,这是我到目前为止所做的:
//调用 2 API URL 的登录方法
login(data){
const Option ={ headers: new HttpHeaders({'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json',"USER_CODE":data.USER_CODE})};
this.http.post<any>(`${environment.baseUrlUserSecurity}/users/login`, data, Option)
.pipe(
map(value => value[0]))
.subscribe( value => {
this.userId = value.result.userId;
this.http.get(`${environment.baseUrlUserSecurity}/prsnls`, this.userId)
.subscribe( user => {
this.user = user;
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
});
})
}
//按下按钮时的提交动作
onSubmit(){
const data = this.loginForm.getRawValue();
this.submitted = true;
localStorage.setItem('USER_CODE',data.USER_CODE);
this.loading = true;
this.isLoading = true;
of(null)
.pipe(
delay(2000),
first()
)
.subscribe(() => {
this.isLoading = false;
this.authService.login(data).subscribe(
(res:any)=>{
if (res.code==200){
localStorage.setItem('token',res.result.token);
localStorage.setItem("infos", JSON.stringify(res.result.roleIds));
localStorage.setItem("prsl", res.result.userId);
//this.getUserInfos(res.result.userId);
this.router.navigate(['/dashboard']);
}
this.rMessage = '';
},
error => {
this.rMessage = 'bError';
this.loading = false;
}
);
});
}
问题是编辑器说'subscribe()'属性在onsubmit()函数内的类型void上不存在this.authService.login(data).subscribe()
而且我不明白为什么我不能订阅那个 observable。如果有人能提供帮助,我将不胜感激,因为我不知道如何解决这个问题并让编辑器没有错误。提前致谢。
记住:“您的服务 return observables,您订阅组件”
每次您在服务中写“订阅”时,您都在犯错误 (*)
好吧,你需要 return 一个基于另一个的可观察对象,所以你需要使用 switchMap rxjs 运算符。 switchMap 总是挡路
observable1(data).pipe(switchMap(res=>{
//here res is the response of the observable1(data)
//you return another observable based in res
return observable2(res)
})
您的登录
login(data){
const Option ={ headers: new HttpHeaders({'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json',"USER_CODE":data.USER_CODE})};
//see that you "return" an observable
return this.http.post<any>(`${environment.baseUrlUserSecurity}/users/login`, data, Option)
.pipe(
switchMap(value=>{
const userId=value[0].result.userId
return this.http.get(`${environment.baseUrlUserSecurity}/prsnls`, userId)
})
现在您可以订阅了
onSubmit(){
const data = this.loginForm.getRawValue();
this.submitted = true;
this.authService.login(data).subscribe(
(res:any)=>{
if (res.code==200){
localStorage.setItem('token',res.result.token);
localStorage.setItem("infos", JSON.stringify(res.result.roleIds));
localStorage.setItem("prsl", res.result.userId);
//this.getUserInfos(res.result.userId);
this.router.navigate(['/dashboard']);
}
this.rMessage = '';
},
error => {
this.rMessage = 'bError';
this.loading = false;
}
);
});
(*)好吧,你可以在你的服务中加入一些像
subject=new Subject<any>()
getData(){
this.httpClient.get(...).subscribe(res=>{
this.subject.next(res)
})
}
然后您订阅“主题”并调用函数
this.authService.subject.subscribe(res=>{
...
})
this.authService.getData();
但它适用于一些“特殊情况”
Update 有时,我们还需要内部 Observable 的数据,我们还需要使用另一个 rxjs 运算符的第一个 observable 的数据 map
我们可以做到
observable1(data).pipe(switchMap(respose1=>{
return observable2(response1).pipe(map(response=>(
{response1:response1,response2:response2}
)))
})
我们有一个具有两个属性的对象:response1 和 response2
我们也可以使用展开运算符进行映射
observable1(data).pipe(switchMap(respose1=>{
return observable2(response1).pipe(map(response=>(
{...response1,...response2}
)))
})
然后我们得到一个具有 response1 和 response2 的所有属性的唯一对象
您需要 return Observable
从 login 方法。
如果您订阅并且 return 那么将会 returning Subcription
type.So in-order 到 return Observable
并且操作结果并在响应出现后做一些事情你必须使用 pipe
.
我改变了你的登录方法如下
login(data): Observable<any> {
const Option = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
USER_CODE: data.USER_CODE,
}),
};
return this.http
.post<any>('${environment.baseUrlUserSecurity}/users/login', data, Option)
.pipe(
map((value) => value[0]),
tap((value) => (this.userId = value.result.userId)),
switchMap((value) =>
this.http
.get<User>('${environment.baseUrlUserSecurity}/prsnls', this.userId)
.pipe(
tap((user:User) => {
this.user = user;
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
}),
map((user) => ({ ...user, ...value }))
)
)
);
}