如何在 Angular 8 中处理异步 HTTP 调用?

How to handle async HTTP calls in Angular 8?

所以我是 Angular TypeScript 的新手,我遇到了问题。

所以我这里有两个文件,一个是我的组件文件,其中包含我在屏幕上使用的功能,第二个是我调用服务器的 HTTP 服务文件。

目前我的代码结构是,

UserProfileComponent.ts

import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';

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

  dataObj: any;

  constructor(private userService: UserService) {
    this.dataObj = this.userService.testCall();
    console.log('dataObj-> ' + JSON.stringify(this.dataObj));
  }

  ngOnInit() {
  }

}

user.service.ts我有这个电话

  testCall(): any{
    let responseObj: any;
    this.http.get(`${this.baseUrl}/users`).subscribe((data) => {
      console.log('responseObj-> '+JSON.stringify(data));
      responseObj = data;
    });
    return responseObj;
  }

所以这个问题对我来说是处理异步调用,console.log('dataObj-> ' + JSON.stringify(this.dataObj)) 不等待服务调用结束,因此打印 undefined.

我知道这是可行的,但我该如何以编程方式处理它?

我需要在继续下一行之前的响应数据。

Angular CLI:8.3.25, 节点:12.16.1, OS: win32 x64, Angular: 8.2.14

问题是您在您的服务中执行 subscribe,但您应该在您的组件中执行,而 return Observable 从服务中执行。

所以最终代码应该是这样的:

testCall(): Observable<UserType[]> {
  //I suppose you return Array of Users
  return this.http.get(`${this.baseUrl}/users`);
}

和组件

export class UserprofileComponent implements OnInit {
  dataObj: UserType[];

  constructor(private userService: UserService) {        
  }

  ngOnInit() {
    this.userService.testCall()
      .subscribe((response: UserType[]) => {
        dataObj = response;
        console.log('dataObj-> ' + JSON.stringify(this.dataObj));
      });
  }
}

正如@Yury 所解释的,您需要从服务级别获取组件级别的订阅。

为了让它变得更好,您可以做的是, 创建一个 API 服务,如下所示:

api.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError, timeout, retry } from 'rxjs/operators';
import { CookieService } from 'ngx-cookie';
import { SERVER } from './static/static.json';

@Injectable({
    providedIn: 'root'
})


export class ApiService {
    user: Observable<any>;
    headers: HttpHeaders;

    constructor(
        private http: HttpClient,
        private cookieService: CookieService
    ) { }
    get(url: string, options?: any) {
        let key = SERVER.api + url;
        this.headers = new HttpHeaders();
        if(typeof options == 'string' && options != " "){
            this.headers = new HttpHeaders().append('Authorization', options);
        }
        return this.http.get(key, {headers: this.headers, withCredentials: false})
        .pipe(
            timeout(15000),
            retry(5),
            catchError(err => throwError(err))
        )
    }
    post(url: string, data: any, options?: any) {
        let key = SERVER.api + url;
        this.headers= new HttpHeaders();

        if(typeof options == 'string' && options != " "){
            this.headers = new HttpHeaders().append('Authorization', options);
        }

        return this.http.post<any>(key , data, {headers: this.headers, withCredentials: false})
        .pipe(
            catchError(err => throwError(err))
        );
    }

    put(url: string, data: any, options?: any) {
        let key = SERVER.api + url;
        this.headers= new HttpHeaders();

        if(typeof options == 'string' && options != " "){
            this.headers = new HttpHeaders().append('Authorization', options);
        }

        return this.http.put<any>(key , data, {headers: this.headers, withCredentials: false})
        .pipe(
            catchError(err => throwError(err))
        );
    }

    delete(url: string, options?: any) {
        let key = SERVER.api + url;
        this.headers= new HttpHeaders();

        if(typeof options == 'string' && options != " "){
            this.headers = new HttpHeaders().append('Authorization', options);
        }

        return this.http.delete<any>(key, {headers: this.headers, withCredentials: false})
        .pipe(
            catchError(err => throwError(err))
        );
    }

}

然后创建一个模块级服务,

abs.service.ts

import { Injectable } from '@angular/core';
import { ApiService } from './shared/api.service';
import { AuthService } from './shared/auth.service';
@Injectable({
    providedIn: 'root'
})
export class ABSService {

    constructor(
        private _API: ApiService,
        private _AUTH: AuthService
    ){}
    getUsers(option?) {
        let url = '/users';
        let token;
        if(option){
            url = url + "?" + option;
        }
        if(this._AUTH.loginCheck()){
            token = this._AUTH.getCookie();
        }
        return this._API.get(url, token);
    }

    postUsers(data) {
        let url = '/users';
        let token;
        if(this._AUTH.loginCheck()){
            token = this._AUTH.getCookie();
        }
        return this._API.post(url,data, token);
    }
}

然后你可以像这样在模块级组件中使用这个模块级服务:

abs.component.ts

import { Component, OnInit } from '@angular/core';
import { ABSService } from './abs.service';

@Component({
    selector: 'app-abs',
    templateUrl: './abs.component.html',
    styleUrls: ['./abs.component.css']
})

export class ABSComponent implements OnInit {
    constructor(
        private _API: ABSService
    ) {}
    ngOnInit(){
        this._API.getUsers().subscribe(
            (data:any)=>{
                // something related to data
                this.dataObj = data;
                console.log('dataObj-> ' + JSON.stringify(this.dataObj));
            },
            (err)=>{
                // something related to error
            }
        )
    }
}

我更喜欢将 HTTP 模块分开,因为上次他们用 HttpClient 模块更改 HTTP 模块时,我不得不做很多工作。