我无法在Angular 13中观察到的Mergemap上订阅

发布于 2025-01-23 00:27:31 字数 2537 浏览 2 评论 0原文

我想根据Angular的角色实施Connexion Senario。当用户填写表单后(用户名 - 密码)后单击连接按钮时,请使用两个API URL使用相同的连接,并且我将Angular 13用于前端。在后端,我有两个端点(Ressources请求URL)用于连接过程。第一个Ressource

this.http.post($ {emovenese.baseurlusersecurity}/users/user/login, 数据,选项)

提供了用于身份验证和第二个ressource的令牌

this.http.get($ {emoverun.baseurlusersecurity}/prsnls, this.userid)

必须根据令牌firt api呼叫提供的用户ID来查找用户的角色。与Postman进行测试时,一切都很好。但是我正在努力与Angular在前端中实现连接过程,这是我到目前为止所做的:

//登录方法,该方法调用2个API urls

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;
              }
          );
      });


  }

问题时,onsubmit Action是编辑说' subscribe()'属性不存在于onsubmit()函数this.authservice.login(data).subscribe()上的onsubmit()函数内部的类型void上不存在而且我不明白为什么我不能订阅可观察到的。我很感谢是否有人提供帮助,因为我不知道如何解决此问题并在没有错误的情况下获取编辑器。提前致谢。

I want to implement a connexion senario based on Roles in angular. When the user click on CONNEXION button after filling in the form ( username - password), two API urls are called to serve the same connexion and I'm using angular 13 for the frontend. In the backend I have the two endpoints ( ressources request url ) to serve the connexion process. The first ressource

this.http.post(${environment.baseUrlUserSecurity}/users/login,
data, Option)

provides the token for authentication and the second ressource

this.http.get(${environment.baseUrlUserSecurity}/prsnls,
this.userId)

has to find the user's role based on the userId provided by the firt API call from the token. Everything works fine when testing with postman. But I'm struggling to implement the connexion process in the frontend with angular and this is what I have done so far:

//LOGIN METHOD THAT CALLS THE 2 API URLs

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;
        });
      })
    }

//THE ONSUBMIT ACTION WHEN THE BUTTON IS PRESSED

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;
              }
          );
      });


  }

The problem is that the editor says the 'subscribe()' property does not exist on type void inside the onsubmit() function on the line this.authService.login(data).subscribe() and I don't understand why I can't subscribe to that observable. I appreciate if anyone can help, because I don't know how to fix this and get the editor without errors. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安静被遗忘 2025-01-30 00:27:31

请记住:“您的服务返回可观察物,您

每次在服务中撰写“订阅”时,您会订阅“订阅”,您会陷入不良练习中(*)

,您需要返回基于另一个的可观察到的,因此您需要使用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();

,但对于某些“特殊情况”

更新有时,futhermore内部观察值的数据我们还需要第一个可观察到的数据,我们需要使用另一个RXJS操作员map

我们

   observable1(data).pipe(switchMap(respose1=>{
       return observable2(response1).pipe(map(response=>(
         {response1:response1,response2:response2}
       )))
    })

有一个具有两个属性的对象:响应2

好吧,我们也可以使用传播运算符映射

   observable1(data).pipe(switchMap(respose1=>{
       return observable2(response1).pipe(map(response=>(
         {...response1,...response2}
       )))
    })

,并且我们获得了一个唯一的对象,该对象具有响应的所有属性1和Response2

Remember: "your services return observables, you subscribe in components"

Each time you write "subscribe" in your service you're falling in a bad practice (*)

Well, you need return an observable based in another one, so you need use switchMap rxjs operator. switchMap is always in the way

observable1(data).pipe(switchMap(res=>{
   //here res is the response of the observable1(data)
   //you return another observable based in res
   return observable2(res) 
})

Your login

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)

       })

Now you can subscribe

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;
              }
          );
      }); 

(*)well you can to have in your service some like

subject=new Subject<any>()
getData(){
   this.httpClient.get(...).subscribe(res=>{
       this.subject.next(res)
   })
}

And you subscribe to the "subject" and call to the function

this.authService.subject.subscribe(res=>{
   ...
})
this.authService.getData();

But it's for some "special cases"

Update Sometime, futhermore the data of the inner Observable we need also the data of the first observable we need use another rxjs operator map

We can do

   observable1(data).pipe(switchMap(respose1=>{
       return observable2(response1).pipe(map(response=>(
         {response1:response1,response2:response2}
       )))
    })

And we have an object with two properties: response1 and response2

Well we can map also using spread operator

   observable1(data).pipe(switchMap(respose1=>{
       return observable2(response1).pipe(map(response=>(
         {...response1,...response2}
       )))
    })

And we get an unique object with all the properties of response1 and response2

歌入人心 2025-01-30 00:27:31

您需要从登录方法返回可观察的

如果您订阅并返回,则将返回subcription type.so返回可观察并操纵结果并在响应后做一些事情,您必须使用管道

我更改了您的登录方法如下

  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 }))
            )
        )
      );
  }

You need to return Observable from login method.

If you subscribe and return then will be returning Subcription type.So in-order to return Observable and manipulate result and do some stuff after response came you have to use pipe.

I changed your login method like below

  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 }))
            )
        )
      );
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文