如何声明带参数的 GET 调用?

How do you declare a GET call with parameters?

从 API 获取数据的一种技术是在服务中像这样声明它:

getItems$ = this.httpClient.get<Item[]>(this.url);

然后要么订阅它,要么在消费组件中使用异步。

如果 get 调用需要像通过 id 获取这样的参数,你会怎么做?

编辑:以上是使用 RxJS 流的声明式方法的示例。 getItems$ 是 属性.

所以问题是,当使用带有 属性 的声明式方法定义流而不是调用 getItems(itemId) 方法时,您如何通过在参数中?

要处理任何“参数”,您可以使用 Subject 或 BehaviorSubject 创建另一个操作流。然后将“参数”发送到流中。

这是我的一个应用程序的示例。

  // Handle product selection action
  private productSelectedSubject = new BehaviorSubject<number>(0);
  productSelectedAction$ = this.productSelectedSubject.asObservable();

  product$ = this.productSelectedAction$
    .pipe(
      filter(id => !!id),
      switchMap(selectedProductId =>
        this.http.get<Product>(`${this.productsUrl}/${selectedProductId}`)
      ));

  // Selected product was changed
  changeSelectedProduct(selectedProductId: number): void {
    this.productSelectedSubject.next(selectedProductId);
  }

这里我们创建一个初始值为 0 的 BehaviorSubject。(您也可以使用没有初始值的 Subject。)

当用户选择一个产品(或者无论如何确定特定产品)时,该产品的 id 被发送到 productSelectedSubject

此代码然后使用管道在每次有新产品 ID 发送到流中时做出反应。管道中的第一个运算符会过滤掉所有无效的 ID。然后 switchMap 使用发出的产品 ID 发出 http get。

我有一个完整的例子,它还为分页设置了额外的“参数”:https://github.com/DeborahK/Angular-ActionStreams

这取决于您请求的 http api。 由于 get 请求没有主体,因此通常将参数添加到 url 中,如下所示: http://example.com/customer?id=25

HttpClient 的 get、post、put 等方法有第二个选项参数,它可以有一个类型为 HttpParams 的参数 属性,其中你可以设置参数 data$ = this.http.get<item[]>(this.url,{params: new HttpParams().set('id',25)}) `

这将处理添加到实际请求的 url。

我喜欢你的问题。我也总是尝试以声明的方式定义我的可观察对象。但是,当涉及到带参数的方法时(尤其是在 Angular 服务中 ),我倾向于只使用 return observables 的函数:

class ItemService {
  public getItem(id: string) {
    return this.http.get<Item>(`${this.apiRoot}/items/${id}`);  
  }
}

如果服务本身负责管理这些“参数”的状态,那么使用 @DeborahK 提到的主题来为消费者提供传递值的便利是有意义的。

但是,如果组件负责这些参数,则通常不需要有 Subjects,因为这些参数值通常来自其他可观察的来源,例如反应式表单控件或路由参数。

例如:

class ItemComponent {
  private id$ = this.route.paramMap.pipe(params => params.get('id'));

  public item$ = this.id$.pipe(
    switchMap(id => this.itemService.getItem(id))
  );
  
  constructor(
    private route: ActivatedRoute,  
    private itemService: ItemService
  ) { }
}

注意在组件中,item$ 仍然以您喜欢的声明方式定义。另请注意,我做了@DeborahK 提到的并从另一个流定义它(另一个流恰好是一个不同的可观察对象,而不是一个主题)。