介绍

我正在尝试使用共享服务中的Observable在Angular2+中创建路由保护,该服务保留了当前用户 Angular 色的字符串值。
问题显然出在我的思维从应许转向可观察。





尝试(由于@ danday74而得到改进)

RxJS sequence equvalent to promise.then()?的帮助下,我已经将我想做的事情翻译成以下内容:

canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | boolean {
        return this.auth.isRoleAuthenticated(route.data.roles)
            .mergeMap((isRoleAuthenticated: boolean) => {
                return isRoleAuthenticated ? Observable.of(true) : this.auth.isRole(Roles.DEFAULT_USER);
            })
            .do((isDefaultUser: boolean) => {
                const redirectUrl: string = isDefaultUser ? 'SOMEWHERE' : 'SOMEWHERE_ELSE';
                this.router.navigate([redirectUrl]);
            })
            .map((isDefaultUser: boolean) => {
                return false;
            });
    }

问题

如果使用isRoleAuthenticated = true,如何停止可观察链的进一步传播?如果满足这样的条件,我需要返回该 bool 值,并确保之后不调用.do运算符块。
限制是必须从canActivate Guard返回 bool 值。

最佳答案

从第一个mergeMap返回的任何内容都会传递到第二个mergeMap,这样它就不会停止进一步传播。如果要停止传播,请使用过滤器(尽管在这种情况下可能会导致挂起)。
仅在返回Observable时才使用mergeMap,但无需从第二个mergeMap返回Observable。做就是了:

  .mergeMap((isRoleAuthenticated: boolean) => {
    if (isRoleAuthenticated) {
      return Observable.of(true)
    }
    return this.auth.isRole(Roles.DEFAULT_USER)
  })
  .tap((isDefaultUser: boolean) => {
    if (isDefaultUser) {
      this.router.navigate(['SOMEWHERE'])
    } else {
      this.router.navigate(['SOMEWHERE_ELSE'])
    }
  })
  .map((isDefaultUser: boolean) => {
    return false
  })
另外,您正在使用RxJs v5语法,但应使用v6。在v6中,运算符-mergeMap,tap,map-用逗号分隔在管道中。
路由器导航是否有可能阻止最终返回并导致挂起?注释掉它,看看它是否可以停止挂起。
不确定是否可以完全解决您的问题,但希望凌晨1点有一些有用的见解
我假设这些返回Observables:
  • this.auth.isRole经过身份验证的
  • this.auth.isRole(Roles.DEFAULT_USER)

  • 如果他们不这样做,您将遇到问题。
    解决方案
    与其专注于停止链,不如创建一个由收集的Observable的结果组成的对象,并将其进一步传播,从而解决了问题:
    canActivate(route: ActivatedRouteSnapshot): Observable<boolean> | boolean {
        return this.auth.getRole()
            .mergeMap((role: string) => {
                return this.auth.isRoleAuthorized(route.data.roles)
                    .map((authorized: boolean) => ({
                        role: role,
                        authorized: authorized
                    }));
            })
            .do((markers: { role: string, authorized: boolean }) => {
                const redirectUrl: string = markers.role === Roles.DEFAULT_USER ? 'SOMEWHERE' : 'SOMEWHERE_ELSE';
                this.router.navigate([redirectUrl]);
            })
            .map((markers: { role: string, authorized: boolean }) => {
                return markers.authorized;
            });
    }
    

    关于angular - 如果满足某些条件,RXJS停止可观察链的传播,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52845192/

    10-17 02:54