简体   繁体   English

在 Angular 中使用带有 RxJS 的声明式/反应式数据访问方法时如何“传递”数据?

[英]How to “pass” data when using a declarative/reactive data access approach with RxJS in Angular?

The classic pattern for data access in Angular suggests code like this: Angular 中数据访问的经典模式建议如下代码:

Classic Data Access Pattern经典数据访问模式

getProducts(): Observable<Product[]> {
  return this.http.get<Product[]>(this.productsUrl)
    .pipe(
      tap(data => console.log(JSON.stringify(data))),
      catchError(this.handleError)
    );

Above we have a method the returns an Observable.上面我们有一个方法返回一个 Observable。 When the data is returned from the http endpoint, that Observable emits the data in a shape defined by the Product[] generic parameter where Product is an interface.当数据从 http 端点返回时,该 Observable 以Product[]泛型参数定义的形状发出数据,其中Product是一个接口。

For a more reactive application, the declarative/reactive approach is often suggested.对于更具反应性的应用程序,通常建议使用声明性/反应性方法。 It changes the above method to a property declaration like this:它将上述方法更改为如下属性声明:

Reactive Data Access Pattern反应式数据访问模式

products$ = this.http.get<Product[]>(this.url)
  .pipe(
    tap(data => console.log(JSON.stringify(data))),
    catchError(this.handleError)
  );

Notice that this declares a property in the service for the Observable instead of a method.请注意,这在服务中为 Observable 声明了一个属性,而不是一个方法。 The $ suffix on products$ is a convention used to distinguish properties that are Observables vs other types of data structures such as general objects or arrays. products$上的$后缀是用于区分 Observable 属性与其他类型的数据结构(例如通用对象或数组)的约定。

This pattern is often used when there is UI interactivity (such as filtering based on a selection), when working with complex data (such as combining data from multiple end points) and when sharing data across components (such as when each component needs to react when the data changes).当存在 UI 交互性(例如基于选择的过滤)、处理复杂数据(例如组合来自多个端点的数据)以及跨组件共享数据(例如每个组件需要做出反应时)时,通常会使用此模式当数据发生变化时)。

The reactive data access pattern presents a common problem.反应式数据访问模式存在一个常见问题。 How do we "pass" data required by the URL when using this technique?使用这种技术时,我们如何“传递”URL 所需的数据?

For example, say that the http request requires a category to only pull down products for that category:例如,假设 http 请求需要一个类别来只下拉该类别的产品:

this.http.get<Product[]>(`${this.url}?cat=${catId}`)

How can this category be "passed in" since there is no method?没有方法怎么能把这个类“传入”?

Instead of thinking how to "pass" data, think instead about how to "emit" that value over time.与其考虑如何“传递”数据,不如考虑如何随着时间的推移“发出”该值。 To emit data, we define our own Observable using Subject or BehaviorSubject .为了发出数据,我们使用SubjectBehaviorSubject定义我们自己的 Observable。

private categorySubject = new Subject<number>();
categorySelectedAction$ = this.categorySubject.asObservable();

products$ = this.categorySelectedAction$.pipe(
 switchMap(catId=>this.http.get<Product[]>(`${this.url}?cat=${catId}`))
    .pipe(
      tap(data => console.log(data)),
      catchError(this.handleError)
  ));

selectedCategoryChanged(categoryId: number): void {
  this.categorySubject.next(categoryId);
}

In the above code, we define our Observable using a Subject .在上面的代码中,我们使用Subject定义了 Observable。 We declare the Subject private so it cannot be accessed from outside our service.我们将 Subject 声明为私有,因此无法从我们的服务外部访问它。 We then expose the read-only part of that Subject using asObservable() .然后我们使用asObservable()公开该主题的只读部分。

Whenever the user selects a different category, the component calls selectedCategoryChanged which emits the selected categoryId into the stream defined by our Subject.每当用户选择不同的类别时,该组件都会调用selectedCategoryChanged ,它将选定的 categoryId 发送到我们的主题定义的流中。

For products$ , when a value is emitted, it is piped through a set of operators.对于products$ ,当发出一个值时,它会通过一组操作符进行管道传输。 The switchMap is a higher-order mapping operator that automatically subscribes to the inner Observable (the this.http.get... ) and flattens the result. switchMap是一个高阶映射操作符,它自动订阅内部 Observable( this.http.get... )并将结果展平。 The returned products for the specified category are then emitted into the products$ stream.然后将指定类别的返回产品发送到products$流中。

To see a more complete solution, see this github: https://github.com/DeborahK/Angular-RxJS/tree/master/APM-Final要查看更完整的解决方案,请参阅此 github: https : //github.com/DeborahK/Angular-RxJS/tree/master/APM-Final

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Angular 中使用反应式方法 RXJS 时如何在合并扫描中调用服务 - How to call a SERVICE inside a Merge Scan when using the Reactive Approach RXJS in Angular 如何做一个简单的 angular Jasmine 单元测试时使用 RXJS 使用主题的反应方法和调用服务的 stream - How to do a simple angular Jasmine Unit testing when using RXJS reactive approach using a subject and a stream that calls a service 如何在 RXJS Angular 中的 concatmap 之间传递数据 - how to pass data between concatmap in RXJS Angular Angular 应用程序中声明式和反应式方法之间的摩擦 - Frictions between Declarative and Reactive approach in Angular app 使用声明性 RxJS,有没有办法将 Observable 数据从父组件传递给子组件? - Using declarative RxJS, is there a way to pass Observable data to child component from parent component? RxJS Angular 如何动态访问数据 - RxJS Angular How to access data dynamically 如何在Angular中将其他数据传递到反应性动态形式 - How to pass additional data to a reactive dynamic form in Angular Angular 使用 RxJS - 当 JSON 对象具有多个属性时如何映射数据 - Angular using RxJS - How to map data when JSON object has multiple properties angular 中的单元测试声明方法 - How unit-test declarative approach in angular 如何在Angular中使用RXJS重试http请求直到收到数据 - How to retry a http request untill a data is recieved using RXJS in Angular
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM