Angular-创建服务以从服务器检索数据并将其发送到使用该数据的组件的正确方法是什么?

时间:2018-10-12 09:00:52

标签: angular angular-promise angular-services

我正在使用Angular(v6.0.0)开发一个Web应用程序。我有一台公开API来检索产品的服务器。一切正常,但是我想知道我所做的以及我如何做到的都是正确的。如果没有,我想知道是否有人可以帮助我改善我的代码。

以下是我的HttpService,我将其用作HttpClient的扩展名,因为我必须在请求的URL中设置使用的语言:

HttpService

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

import { environment } from '../../../environments/environment';
import { TranslateService } from '@ngx-translate/core';

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

  constructor(
    private http: HttpClient,
    private translate: TranslateService
  ) { }

  /**
   * General GET request
   *
   * @param {string} url URL of the request
   * @param {HttpParams} [params]
   * @returns {Promise<any>}
   * @memberof HttpService
   */
  async get(url: string, params?: HttpParams): Promise<any> {
    return await this.http.get<any>(`${environment.apiURL}${this.translate.getDefaultLang()}/${url}`, { params: params }).toPromise();
  }
}

然后我有 ProductService

import { Injectable } from '@angular/core';
import { HttpService } from '../http/http.service';
import { Product } from 'src/app/models/product';
import { HttpParams } from '@angular/common/http';

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

  constructor(
    private httpService: HttpService
  ) { }

  async getProductsByCategory(categoryId: string): Promise<Product[]> {
    let res = await this.httpService.get('products', new HttpParams().set('category', categoryId).set('perPage', '1000'));
    return res.data;
  }
}

请注意,我知道产品的数组为res.data

现在,在使用ProductService的组件中,执行以下操作:

this.products = await this.productService.getProductsByCategory(ID);

正如我在问题开始时所说的那样,一切似乎都按预期工作,但是我对我阅读的所有有关承诺及其使用方法的文章感到困惑,所以我想问一下你们这是使用诺言的正确方法还是我需要改进代码。

感谢您的回复!

3 个答案:

答案 0 :(得分:0)

我在这里唯一的建议是不要使用 Promise ,因为 Observable 可以很容易地在代码中使用这些服务的地方使用。

答案 1 :(得分:0)

按照我的看法,您的HttpService可以转换为http拦截器。尤其是如果您只有一个API端点。

ProductService中,出于两个主要原因,我将返回一个可观察的结果,而不是一个诺言:

  1. 可观察项是可取消的。因此,也许一个请求需要花费更长的时间,并且用户改变了主意,您希望能够取消该请求,并让服务器停止处理该请求(如果这对服务器来说是一件很费力的事情)。

  2. 当某些更改和承诺无法做到时,您的服务可能演变为推送新项目。例如,您有一个具有items$和某些add / delete方法的通用回购服务。您可以更改服务以在add / delete正常工作时立即更新项目,例如以下示例:How do I add an item to an Observable<Entity[]> type from an API response, if the Observable is being handled by the async pipe?

答案 2 :(得分:0)

我将为您提供在我们的项目中使用的示例代码。

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../../environments/environment';
import { Observable } from 'rxjs';
import { httpOptions } from '../../http-options';
import { Content } from '../../content.model';

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

  private reportPredefinedContentApi = `${environment.baseUrl}/report/report-predefined-contents`;

  constructor(private httpClient: HttpClient) { }

  getList(reportSectionId : number) : Observable<Content[]>{
    return this.httpClient.get<Content[]>(`${this.reportPredefinedContentApi}/${reportSectionId}`, httpOptions);
  }

}

在component.ts中,

reportSectionId: number;
contents: Content[] = [];

constructor(private predefinedTextService: PredefinedContentService) {}

getContentList() {
    this.predefinedTextService
      .getList(this.reportSectionId)
      .subscribe(result => {
        this.contents = result;
        },error => {
           console.log(error)
        });
}