Angular5 中 returns HttpClient 响应的函数?

function which returns HttpClient response in Angular5?

我遵循了 "Tour of heroes" Angular 教程,并且可以应用相同的机制从网络服务中检索项目列表并将其显示在 table.

现在我正在编写一个调用网络服务来检查凭据的函数。此网络服务 returns 一行:{ "msg": "Hello username" }

login.component.html:

[...]
<a class="btn rounded-btn" [routerLink]="['/dashboard']" (click)="onLogIn(loginForm)"> Log in </a>
[...]

login.component.ts:

export class LoginComponent implements OnInit {

    constructor(public router: Router,
                private loginService: LoginService) {}

    ngOnInit() {
    }

    onLogIn(loginForm: any) {
        let authResponse = this.loginService.check_credentials(loginForm.controls.login.value, loginForm.controls.password.value);
        console.log(authResponse)
        localStorage.setItem('isLoggedin', 'true');
    }

login.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class LoginService {
    private wsLoginUrl = '/api/check_login';

    wsResponse;

    constructor(private http: HttpClient) { }

    check_credentials(login: string, password: string): string {
        this.getResponse().subscribe(response => this.wsResponse = response);
        this.getResponse().subscribe(response => console.log(response));
        console.log(this.wsResponse);
        return "ok" 
    }

    getResponse() { 
        return this.http.get(this.wsLoginUrl);
    }    
}

控制台输出为:

undefined                          login.service.ts:43:12
ok                                 login.component.ts:25:8
Object { msg: "Hello username" }   login.service.ts:34:53 

由于 'ok' 在 web 服务响应之前,我想一旦 subscribe(...) 完成,功能代码就会继续。然后,当网络服务响应时,订阅代码被执行:console.log(response) and this.wsResponse = response.

如何创建一个等待网络服务响应的函数?

我尝试了不同的方法,使用 map() 或其他 SO 答案,但我找不到如何做到这一点。


更新了代码,感谢 Rubén Soler 的回答,现在可以使用了:

login.service.ts:

import { Injectable }              from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable()
export class LoginService {
    private wsLoginUrl = '/api/check_login';

    constructor(private http: HttpClient) { }

    async checkCredentials(login: string, password: string) {
        try {
            let response = await this.getResponse().toPromise();
            return response;
        } catch(e) {
            console.error(e);
        }
    }

    getResponse() { 
        return this.http.get(this.wsLoginUrl);
    }

}

login.component.ts:

import { Component, OnInit }      from '@angular/core';
import { Router }                 from '@angular/router';
import { routerTransition }       from '../router.animations';
import { FormGroup, FormControl } from '@angular/forms';
import { LoginService }           from './login.service';

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.scss'],
    animations: [routerTransition()]
})
export class LoginComponent implements OnInit {

    constructor(public router: Router,
                private loginService: LoginService) {}

    ngOnInit() {
    }

    onLogIn(loginForm: any) {
        this.loginService.checkCredentials(loginForm.controls.login.value, loginForm.controls.password.value)
            .then((resp) => { 
                if (resp['msg'] == 'hello') {
                    console.log('Resp is ok')
                    localStorage.setItem('isLoggedin', 'true');
                    this.router.navigate(['dashboard']);
                }
                else {
                    console.log('Resp is NOT ok')
                    //Other things...
                }
            } );
    }

}

该应用程序运行良好,但您只需要分析您的执行流程。

先打印undefined因为第一个订阅还在等待

console.log(this.wsResponse);

第二次打印正常,因为你在 check_credentials 函数中 return 'ok'(真诚地),并在你使用它时在组件中打印。

let authResponse = this.loginService.check_credentials(loginForm.controls.login.value, loginForm.controls.password.value);
console.log(authResponse)

之后,订阅者获得响应并在 check_credentials 中异步执行成功函数并打印 { msg: "Hello username" } :

this.getResponse().subscribe(response => this.wsResponse = response);
this.getResponse().subscribe(response => console.log(response));

如果您想在 check_credentials 函数中等待响应,您可以将可观察对象转换为 promise 并像这样使用 async/await (login.service.ts):

async check_credentials(login: string, password: string): string {
       try {           
             let response = await this.getResponse().toPromise();
             this.wsResponse = response;    
             return response
           } catch(e) {
             console.error(e);
           }
}

login.component.ts:

onLogIn(loginForm: any) {
      this.loginService.check_credentials(loginForm.controls.login.value, loginForm.controls.password.value)
        .then((res) => console.log(authResponse))
}

您可以在此处阅读更多相关信息:https://medium.com/@benlesh/rxjs-observable-interop-with-promises-and-async-await-bebb05306875

这里https://ponyfoo.com/articles/understanding-javascript-async-await