【问题标题】:working with synchronous observables in javascript在 javascript 中使用同步 observables
【发布时间】:2017-12-29 12:34:08
【问题描述】:

这个问题在某种程度上与这个问题 1,2 相关,但他们没有以可以帮助我的方式解决 javascript 中的同步 observables 的主题。

我目前处于 angular 4 或只是 angular,并且我有一条受保护的路线等待两名警卫解决。他们两个按预期返回 true,但第二个需要太长时间,所以它的答案是在 canActivate 方法完成之后。下面的示例代码。我该怎么做才能等待我的第二个守卫同步解决?

我是这种 javascript 和 observables 异步处理方式的新手!对不起,如果这个问题很愚蠢。

  1. 第一个 authGuard:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): 
    boolean {
         if(this.cookieService.check('token'))return true;
         console.log(true); //For demostration purpose
    }
    
  2. 第二个 authGuard:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): 
    boolean {
         this.roleService.checkRole('admin') // this service take some time
         .subscribe(
             response=>{
                 //Simple logic checking the response.
                 console.log(true); 
                 return true;
             },
             error=>{
                 //some logic with the error
                 console.log(false);
                 return false;
             }
    
         )
    console.log('End of authguard method');
    }
    
  3. 角色服务:

    checkRole(role:string): 
    boolean {
           return  this.http.post(Url, body,requestOptions)
                            .map(this.processData)
                            .catch(this.handleError);
    }
    

4.控制台显示:

    true                        // from authGuard 1
    "End of authguard method"   // from authGuard 2
    true                        // from authGuard 2

路由器无法导航到期望的路由,因为第二个真的来得太晚了。我也在订阅前尝试了first() 运算符,第一个运算符不等待 role.Service 中的 observable 解析。

【问题讨论】:

  • “同步可观察”是矛盾的。
  • @torazaburo 不过,这不是真的。 RxJS 不保证他们的代码(或他们的订阅者的代码)将在哪个 tick 中运行。如果 observable 来自严格同步的源,那么整个链可能会在当前堆栈上内联运行。如果 observable 的源是异步的,或者您正在异步源中进行 flatMapping(切换,等等),那么您的链是异步的,并且将在那时发生在未来的一组堆栈中。 Promise 保证构造函数是同步的,所有的解析都是异步的; RxJS 没有这样的运气。
  • @paulpdaniels 在角度文档angular example 中使用 canActivate 方法作为布尔值。不过我尝试了你的建议,但问题是我的第二个 authGuard 在 canActivate 方法完成后返回 true,因此无法访问路由。
  • @ramon 是什么意思,returning true after the canActivateMethod 完成了吗?您应该返回一个 Observable,Angular 知道在评估 canActivate 之前等待完成。除非我误解了文档的某些部分
  • @paulpdaniels angular is not waiting for this.roleService.checkRole if you put a console.log('something') at the end of the canActivate 方法,something 在来自@987654334的答案之前打印@ 。我想我最终会重构我的整个代码来解决这个问题。

标签: javascript angular rxjs


【解决方案1】:

CanActivate的接口是

interface CanActivate { 
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|Promise<boolean>|boolean
}

这意味着除了原始布尔值之外,它还将接受PromiseObservable 的返回类型。您面临的问题是您试图将 Observable 视为布尔值,但事实并非如此。您应该将您的第二个 authGuard 重构为:

canActivate(
  route: ActivatedRouteSnapshot, 
  state: RouterStateSnapshot
): Observable<boolean> {
  return this.roleService
     .checkRole('admin') // this service take some time
     // Any success value is mapped to true
     .mapTo(true)
     // Any error will log and return false
     .catch(e => {
       console.log('Encountered an error checking role', e);
       return Observable.of(false);
     })
     // This logs when this *actually* completes
     .finally(() => console.log('End of authguard method'));
}

我们需要执行上述操作的原因是,作为一般模式,我们不知道Observable 何时会发出,我们只知道当它发出时我们想要做什么。我们实际上是在返回一个将最终完成的工作管道,而不是尝试分配单个值来返回。

【讨论】:

    猜你喜欢
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 2019-12-28
    • 2017-09-09
    相关资源
    最近更新 更多