How to wait for a http request to finish in Angula

2020-06-03 09:23发布

问题:

I've been building a SPA with Angular 4 on the front end and ASP.NET Core 2 on the Backend. Basically, I'm trying to automatically renew an user login, given a valid token. When I reload a page, for example, I would like that Angular stayed logged in. I'm storing the token on local storage, as well as an user object so I can check some user properties (if he/she is logged in for example).

How should I force angular to wait for the http request to finish? Here's the .net get Service:

get<T>(url: string): Observable<T> {
    let options = this.doHeaders();
    return this.doSub(this.http.get(this.doUrl(url), options));
}

private doSub<T>(obs: Observable<Response>) {
    var ob1: Observable<T> = obs.map(this.extractData)
        .catch(this.handleError);

    return ob1;
}

Here's the HTTP Request code:

   getUser() {

    if (this.storage.token == null || this.storage.token == '') {
        return;
    }

    this.net.get<LoginModel>(`Authentication/GetUser`).subscribe(t => {
        this.storage.token = t.token;
        this.storage.user = t.user;
        console.log(this.storage.user);
    });
}

Here's how I'm checking for the user:

export class StorageService {

    constructor(
        private storage: LocalStorageService
    ) {
    }

    public user: User = null;

    public get isLoggedIn(): boolean {
        return this.user != null;
    }

}

export class IsLoggedIn implements CanActivate {

constructor(
    private storage: StorageService,
    private router: Router
) { }

canActivate(
    childRoute: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
) {
    if (this.storage.isLoggedIn) {
        return true;
    }

    this.router.navigate(['account/login'], {
        queryParams: {
            return: state.url,
            message: 'You must be logged in'
        }
    });
    return false;
}}

The real issue is: Whenever I try to reload the page on a protected page, Angular does not wait for the http to complete, and redirects me to the login page. After about a few seconds, it logs in, but i've been redirected already. The above code is being executed on AppComponent (NgOnInit). Thanks in advance.

回答1:

You can use promises with async/await

async getUser() {
    if (this.storage.token == null || this.storage.token == '') {
        return;
    }

    const t = await this.net.get<LoginModel>(`Authentication/GetUser`).toPromise();

    this.storage.token = t.token;
    this.storage.user = t.user;

    console.log(this.storage.user);
}

See more:

  • Promises
  • async
  • await
  • ES8 async/await
  • async/await tutorial
  • async/await explained


回答2:

Use .toPromise on your observable followed by async/await.

await this.net.get<LoginModel>(`Authentication/GetUser`).toPromise();


回答3:

You can not use the async/await syntax with Observables returned by Angular HttpClient so you first need to convert the observable to a promise first.

Luckily the Observable interface exports a toPromise() method which returns a promise from the observable:

await this.net.get<LoginModel>('Authentication/GetUser').toPromise();

See this example of how to use Async/Await with Angular HttpClient