Angular 打字稿异步 HTTPClient 调用

Posted

技术标签:

【中文标题】Angular 打字稿异步 HTTPClient 调用【英文标题】:Angular typescript Async HTTPClient call 【发布时间】:2021-11-12 07:48:51 【问题描述】:

我有问题。在我的角度项目中,我正在尝试进行 Http POST 调用,以登录我的网站。我向呼叫提供用户名和密码。如果 API 端点返回 null,则登录失败,如果端点返回 Account 对象,则登录成功。进行 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() 函数总是返回null。我知道我必须使用某种异步/等待,但我似乎无法弄清楚如何在我的情况下使用它。这是我尝试过的。在 AccountService 中:

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;

有人可以告诉我如何解决和优化(如果可能的话)吗?

【问题讨论】:

你能不能把console.log(data)上面的if(data != null) 打印出来,也许你需要先把结果映射出来 【参考方案1】:

问题是login()函数总是返回null

是的,从login 方法返回数据的方式存在问题。您使用 subscribe 异步执行但不返回任何值。你应该使用类似map 的东西。请参阅此帖子以了解更多详细信息:Return a Observable from a Subscription with RxJS

因此,如果您尝试这样的事情(未测试),您的 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
    
)

【讨论】:

以上是关于Angular 打字稿异步 HTTPClient 调用的主要内容,如果未能解决你的问题,请参考以下文章

Angular:如何手动将打字文件添加到打字稿

带有打字稿的 Angular 5 websocket 示例

在 Angular 1.5 中绑定组件函数时如何利用打字稿?

打字稿定义无法导入Angular2

Angular - 打字稿变量范围

Typescript 2 + Angular googlemaps 打字稿定义