Angular 打字稿异步 HTTPClient 调用

Angular typescript Async HTTPClient call

我有问题。在我的 angular 项目中,我正在尝试进行 Http POST 调用,以登录我的网站。我为通话提供了用户名和密码。如果 API 端点 returns 为空,则登录失败,如果端点 returns 一个帐户对象,则登录成功。进行 Http POST 调用的代码如下:

import { Injectable } from '@angular/core';
import {Account} from "../models/Account";
import {Observable} from "rxjs";
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {PostService} from "./post.service";

@Injectable({
    providedIn: 'root'
})
export class AccountService {

    public loggedInAccount: Account | null;

    private httpOptions = {
        headers: new HttpHeaders({
            'Content-Type':  'application/json',
            //Authorization: 'my-auth-token'
        })
    };

    constructor(private httpClient: HttpClient) {
        this.loggedInAccount = null;
    }

    public login(account: Account):Account | null {
        this.restLogin(account).subscribe(
            (data) => {
                if (data != null) {
                    this.loggedInAccount = data;
                }
                return data;
            },
            (error) => {
                alert('Error: Status ' + error.status + ' - ' + error.error);
            });
        return null;
    }


    private restLogin(account: Account): Observable<Account> {
        let email = account.email;
        let password = account.password;
        return this.httpClient.post<Account>('http://localhost:8080/account/login', {email, password}, this.httpOptions);
    }

}

问题是 login() 函数总是 returns 为空。我知道我必须使用某种 async/await,但我似乎无法弄清楚如何在我的案例中使用它。这是我试过的。在账户服务中:

public async login(account: Account):Promise<Account | null> {
    let returnValue = null;
    await this.restLogin(account).subscribe(
        (data) => {
            if (data != null) {
                this.loggedInAccount = data;
            }
            returnValue = data;
        },
        (error) => {
            alert('Error: Status ' + error.status + ' - ' + error.error);
        });
    return returnValue;
}

登录页面:

public onLoginClick(): void {
    let email = (document.getElementById("txtEmail") as HTMLInputElement).value;
    let password = (document.getElementById("txtPassword") as HTMLInputElement).value;

    if (this.accountService.login(new Account(email, password)) != null) {
        this.accountService.loggedInAccount!.posts = this.postService.getAccountPosts(this.accountService.loggedInAccount!.id);
        this.route.navigate(['/']);
    }
    else {
        (document.getElementById("txtMessage") as HTMLDivElement).innerHTML = "Incorrect email/password!"
    }
}

但这让我在登录页面的这一行出现错误:

this.accountService.loggedInAccount!.posts = this.postService.getAccountPosts(this.accountService.loggedInAccount!.id);

this.accountService.loggedInAccount 为空,但这是不可能的,因为我在 de AccountService:

中设置了它
if (data != null) {
    this.loggedInAccount = data;
}
return data;

有人能告诉我如何修复和优化(如果可能)这个问题吗?

The problem is that the login() function always returns null

是的,return 来自 login 方法的数据存在问题。您使用 subscribe 以异步方式执行但不 return 任何值。你应该使用像 map. See this post with more details :

这样的东西

因此,如果您尝试这样的操作(未测试),您的 login 函数应该可以工作:

public login(account: Account): Observable<Account | null> {
    return this.restLogin(account)
        .pipe(
            map(result => {
                // TODO: do something with "result" ?
                // If not, you can remove the "map" pipe and only keep "catchError"
                return result;
            }),
            catchError(error => {
                // TODO: handle error
                return of(null);
            })
        );
}

然后你可以像这样调用你的 login 方法:

this.accountService.login(new Account(email, password)).subscribe(account => {
    if (account !== null) {
        // Login succeeded, redirect
    } else {
       // Login failed
    }
})