初始调用时难以观察到的返回未定义

时间:2019-10-21 10:49:07

标签: angular

我正在用angular 8应用程序编写属性,以检查服务的可用性。该属性调用观察对象进行检查,并返回true或false。 我试图在我的身份验证保护服务中调用此属性。我面临的问题是,当第一次调用该属性时,它返回未定义的值,后来我看到正在执行的订阅中的代码。在执行该属性的if块检查时,它已经不确定,因此不会执行 我该如何处理?

我要实现的目的是通过检查TE服务是否可用将用户从auth Guard自身重定向到脱机页面。有人可以告诉我问题出在哪里吗

我在auth Guard服务中添加的条件块是

if (!isServiceAvailable) {
    this.router.navigate(['/offline'])
    return false
}

授权保护服务

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
    constructor(
        private authService: AuthService,
        private router: Router,
        private alertService: AlertService,
        private connectionService: ConnectionService
    ) {}
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url
        return this.checkLogin(url)
    }
    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.canActivate(route, state)
    }
    canLoad(route: Route): boolean {
        let url = `/${route.path}`
        return this.checkLogin(url)
    }
    checkLogin(url: string): boolean {
        let isLoggedIn = this.authService.isLoggedIn
        let isSessionExpired = this.authService.isSessionExpired
        let isServiceAvailable = this.connectionService.isApiAvailable
        if (!isServiceAvailable) {
            this.router.navigate(['/offline'])
            return false
        }
        // user is logged in and session didn't expire
        if (isLoggedIn && !isSessionExpired) {
            return true
        }
        if (isLoggedIn && isSessionExpired) {
            this.authService.refreshLogin().subscribe()
            return true
        }
        // redirect and logout
        this.authService.loginRedirectUrl = url
        this.router.navigate(['/login'])
        this.authService.logout(isLoggedIn && isSessionExpired)
        return false
    }
}

连接服务

@Injectable()
export class ConnectionService {
    constructor(
        private httpClient: HttpClient,
        private configurationService: ConfigurationService
    ) {
        const source = timer(0, Number(environment.corePingIntervalSeconds) * 1000)
        source.subscribe(() => {
            this.checkIfCoreApiIsAvailable()
                .pipe(first())
                .subscribe(
                    resp => {
                        //  if (resp.status === 200 ) {
                        //   // console.log(true)
                        //  } else {
                        //  //  console.log(false)
                        //  }
                    },
                    err => console.log(err)
                )
        })
    }
    get isApiAvailable(): boolean {
        let isAvailable: boolean
        this.checkIfCoreApiIsAvailable()
            .pipe(first())
            .subscribe(
                resp => {
                    if (resp.status === 200) {
                        isAvailable = true
                    } else {
                        isAvailable = false
                    }
                },
                err => console.log(err)
            )
        return isAvailable
    }
    checkIfCoreApiIsAvailable() {
        var pingUrl = this.configurationService.baseUrl + '/api/online'
        return this.httpClient.get(pingUrl, {
            observe: 'response'
        })
    }
}

1 个答案:

答案 0 :(得分:0)

您将在观察值完成之前返回isAvailable。您需要对其进行更改,以便函数返回可观察到的值:

get isApiAvailable(): Promise<boolean> {

    return this.checkIfCoreApiIsAvailable()
        .pipe(
          first(),
          map(resp  => {
            if (resp.status === 200 ) {
              return true;
            }

            return false;
          })
        )
        .toPromise();
    }

然后您需要在此处处理可观察到的响应:

let isServiceAvailable = await this.connectionService.isApiAvailable;

请注意我如何将可观察的对象转换为一个Promise,以便您可以使用await而不必更改太多代码。确保在checkLogin函数前面加上async关键字,否则使用await会引发错误。

如果您不想使用Promise,则可以简单地调整代码以监听可观察到的响应。