【问题标题】:How to make a function (which calls subscribe method) wait from returning value before data is resolved within subscribe method?在订阅方法中解析数据之前,如何使函数(调用订阅方法)等待返回值?
【发布时间】:2020-06-12 14:35:23
【问题描述】:

我对 Angular 还很陌生,在这里我很感激一些指导。我在 AuthService 中的 userLoggedIn 函数总是返回 false,因为这个函数返回变量 userIsLoggedIn 的值,该变量最初被赋值为 false 并且它永远不会到达代码块 - 在执行 return 语句之前传递给 subscribe 方法的回调函数中的this.userIsLoggedIn=res.tokenValid;。我相信这是由于 javascript 处理函数的异步性,但是如何在完全执行我的回调函数之前阻止执行到达 return 语句,以便我的函数可以返回 true 如果我的响应对象的 validToken 属性包含 true 值?

我尝试了以下方法但没有帮助:

  1. 在我的回调函数上使用了 async-await -

    this.httpReq.verifyToken(token)
        .subscribe(**async** res =>{
        this.userIsLoggedIn= **await** res.tokenValid;
        })```
    
  2. 制作了整个 userLoggedIn 函数async-await

    **async** userLoggedIn():boolean{
         **await** this.httpReq.verifyToken(token)
     }
    
//Auth Service
export class AuthService {
    userIsLoggedIn=false;
    constructor(private router:Router, private repo:ProductRepository, 
        private httpReq:HttpRequestService) {}

    userLoggedIn():boolean{
        const token=this.getLocalToken();

        if(!token){
            return false;
        }

        this.httpReq.verifyToken(token)
            .subscribe(async res =>{
            this.userIsLoggedIn=await res.tokenValid;
            })

        return this.userIsLoggedIn;

    }
}


//verifyToken method in my HttpRequestService
export class HttpRequestService {

    constructor(private http: HttpClient) { }

    verifyToken(token:string){
        const headers=new HttpHeaders({
          'Content-Type':'application/json',
          'Authorization':token
        })

        return this.http.post<{message:string, tokenValid:boolean}>('http://localhost:3000/users/authenticate', null, {headers:headers})

    }
}

【问题讨论】:

    标签: angular async-await subscribe


    【解决方案1】:

    因为您的 userLoggedIn() 函数正在执行 HTTP 调用,所以该函数应该异步发生(一段时间后完成)。

    提示:为了更好地理解sync vs async,请查看回调、异步/等待、承诺、可观察对象。

    答案:

     userLoggedIn(): Observable<boolean>{
            // Make sure this is sync or need to be chained with the observable below
            const token = this.getLocalToken();
    
            if(!token){
                return of(false);
            } else {
                return this.httpReq.verifyToken(token).pipe(
                     // Use the tap operator to update some inner class variable
                     tap((res) => this.userIsLoggedIn = res.tokenValid)
                     // We do have the response, if there is ok you can return true. You can add additional validations.
                     switchMap((res) => res ? of(true) : of(false)),
                     // Catch errors, do something with them
                     catchError((err) => of(false))
                )
            }
        }
    

    小词汇表:

    of:根据提供的参数创建一个新的 observable
    tap:不影响流,可以执行操作而不会对响应产生副作用
    switchMap:类似于.then(() =&gt; new Promise()

    ... 最后像这样调用函数:

       userLoggedIn().subscribe(isLoggedIn => console.log(isLoggedIn);
    

    【讨论】:

    • switchMap((res) =&gt; res ? of(true) : of(false)) 可能只是 map(res =&gt; res.tokenValid) 甚至是 pluck('tokenValid')
    • @fridoo 是的,我们可以使用pluckmap,但我更喜欢switchMap 的冗长和与Promises 的相似性。
    • @AndrewRadulescu 感谢您的解决方案并解释了一些 rxjs 运算符。我正在按照您的建议从我的 authguard 调用 userLoggedIn 函数来测试您的解决方案,但即使 res.tokenValid 为真,它仍然返回“假”;
    • @AndrewRadulescu 这是我的 authguard 服务
    • export class AuthGuard implements CanActivate { userLoggedIn=false; constructor(private auth:AuthService){} canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean { this.auth.userLoggedIn().subscribe(isLoggedIn=&gt;this.userLoggedIn=isLoggedIn); if(this.userLoggedIn){ return true; }else{ // some code// } } }
    【解决方案2】:

    您不需要使用异步或等待。 HttpRequestService.verifyToken 返回一个 {message:string, tokenValid:boolean} 类型的 Observable。您可以让 userLoggedIn 函数也返回此 Observable,然后订阅 userLoggedIn。你需要熟悉 RX Observables,但你可以让 HttpRequestService.verifyToken 返回一个 Promise。在这种情况下,这不是一个坏主意。

    【讨论】:

      猜你喜欢
      • 2020-02-25
      • 1970-01-01
      • 2017-10-08
      • 2019-05-10
      • 2022-06-27
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多