Как заставить функцию (которая вызывает метод подписки) ждать возврата значения, прежде чем данные будут разрешены в методе подписки? - PullRequest
1 голос
/ 17 апреля 2019

Я довольно новичок в Angular и ценю некоторые советы здесь. Моя userLoggedIn функция внутри AuthService всегда возвращает false , потому что эта функция возвращает значение переменной userIsLoggedIn , которая изначально присвоена false , и никогда достигает блока кода - this.userIsLoggedIn=res.tokenValid; внутри функции обратного вызова, переданной методу подписки перед выполнением оператора return. Я полагаю, что это связано с асинхронной природой функций обработки javascript, но как мне предотвратить выполнение до оператора возврата до полного выполнения моей функции обратного вызова, чтобы моя функция могла вернуть true , если свойство validToken моего объекта ответа содержит true значение?

Я попробовал следующее, но не помогло:

  1. использовал функцию асинхронного ожидания в моей функции обратного вызова - 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})

    }
}

Ответы [ 2 ]

1 голос
/ 17 апреля 2019

Поскольку ваша функция 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))
            )
        }
    }

Малый глоссарий:

из : создает новую наблюдаемую предоставленный параметр
tap : не влияет на поток, может выполнять операции без побочных эффектов с ответом
switchMap : аналогично .then(() => new Promise()

... и, наконец, вызовите функцию как:

   userLoggedIn().subscribe(isLoggedIn => console.log(isLoggedIn);
0 голосов
/ 17 апреля 2019

Вам не нужно использовать async или await.HttpRequestService.verifyToken возвращает Observable типа {message: string, tokenValid: boolean}.Вы можете сделать так, чтобы функция userLoggedIn также возвращала этот Observable, а затем делала подписку на userLoggedIn.Вам нужно освоиться с RX Observables, но вы могли бы заставить HttpRequestService.verifyToken вернуть Обещание.В этом случае это неплохая идея.

...