OnInit 正在检索尚未加载的服务 属性

OnInit retrieving Service property which is not yet loaded

我是 Angular 2+(大约一周)的新手,我对可观察部分有疑问。

我有这项服务:

export class GetProductsService {

  allProducts;

  constructor(private http: HttpClient) {
    this.http.get('https://jsonplaceholder.typicode.com/posts').subscribe({
      next: data => this.allProducts = data,
      error: err => console.log(err)
    });
  }

  getAllProducts() {
    return this.allProducts;
  }

在构造函数中,我发出获取请求以检索一些假 "products"。

我检索到的产品,我存储在一个属性中,这样我以后可以更方便地使用属性上的其他功能。

现在这是我的问题:我有这个组件

export class AllProductsComponent implements OnInit {

allProducts: any;

constructor(private http: HttpClient, private productsService: GetProductsService) {}

ngOnInit(): void {
    this.allProducts = this.productsService.getAllProducts();
  }


}

从 ProductService OnInit 检索产品 属性,但是考虑到它是一个可观察对象,当其他组件尝试检索 allProducts 属性 时,它尚未从可观察流

如何解决这个问题,我可以看到这是一个常见的问题,这就是为什么我也要求对这个主题有更多的一般性更好的理解。我知道这是异步的,我知道它是什么。

我试过的:

我尝试只让服务 return Observable 而不是设置它自己的状态,但是当我实现一个函数来检索特定产品时,我必须再次进行 HTTP 调用,而不是使用内部状态。

非常感谢您的宝贵时间!

如果您想在响应 returned 时得到通知,您应该 return 来自服务的可观察对象。

如果您想避免在应用程序的生命周期内发出另一个 http 请求,您可以在第一次响应时缓存响应。

import { of } from 'rxjs';
import { tap } from 'rxjs/operators';

export class GetProductsService {

  private cache = {
    allProducts;
  };

  constructor(private http: HttpClient) { }

  getAllProducts() {
    if (this.cache.allProducts) {
      return of(this.cache.allProducts);
    }

    return this.http.get('https://jsonplaceholder.typicode.com/posts').pipe(
      tap(response => this.cache.allProducts = response)
    );
  }
}

然后您应该在您的组件中订阅此功能。

ngOnInit(): void {
  this.productsService.getAllProducts().subscribe(products => {
    this.allProducts = products;
  });
}

注意 - 这是一种非常简单的状态管理形式,我已经演示了这种模式,以帮助您学习如何使用可观察对象。您会及时遇到更多高级状态管理模式和工具。

我使用这样的 API 服务:

@Injectable()
export class ApiService {
  constructor(
    private http: HttpClient
  ) { }

  private setHeaders(): HttpHeaders {
    const headersConfig = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };

//...

    return new HttpHeaders(headersConfig);
  }

  private formatErrors(errorResponse: any) {
    return Observable.throw(errorResponse.error);
  }

  get(path: string, params: any = {}): Observable<any> {
    return this.http.get(`${environment.api_url}${path}`, { headers: this.setHeaders(), params: params })
    .catch(this.formatErrors);
  }
}

并在我的 ItemService 中像这样使用它:

 query(itemSlug: string): Observable<{ items: Item[] }> {   
    return this.apiService
      .get('/items/' + itemSlug);
  }

在我的控制器中,我像这样使用 ItemService:

this.itemsService.query(this.item.slug).subscribe(data => {
  this.items = data.items;
});

有关此方法的详细信息,请参阅 https://github.com/gothinkster/angular-realworld-example-app