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

时间:2020-03-23 08:44:28

标签: angular rxjs angular2-observables

我对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;
  }

在构造函数中,我获取请求以检索一些假的“产品”。

我将检索到的产品存储在属性中,以便将来可以更轻松地在该属性上使用其他功能。

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

export class AllProductsComponent implements OnInit {

allProducts: any;

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

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


}

这从ProductService OnInit检索product属性,但是考虑到它是可观察的,因此当另一个组件尝试检索allProducts属性时,它尚未从可观察的流中完全加载。

这将如何解决,我可以看到这是一个经常出现的问题,这就是为什么我还要求对该主题有一个更一般的理解。我了解它是异步的,我了解它是什么。

我尝试过的事情

我尝试仅让Service返回Observable而不是设置其自己的状态,但是,当我实现检索特定产品的功能时,必须再次进行HTTP调用,而不是使用内部状态。

非常感谢您抽出宝贵的时间!

2 个答案:

答案 0 :(得分:2)

如果希望在返回响应时得到通知,则应该从服务中返回可观察对象。

如果要避免在应用程序的生命周期内再次发出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;
  });
}

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

答案 1 :(得分:0)

我使用这样的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