目前我正在开发一些模块,在该模块中我们尝试使用异步管道而不是markForCheck等方法。
大多数数据都是通过 HTTP 传输的,整个项目的方法是使用 ChangeDetectionStrategy.OnPush。
通常,我们所有的 BehaviourSubjects
都在我们的“智能”组件中,并且表示组件的值由输入设置。这对于较小的模块来说很好。我们通常有 2-6 个这样的演示组件。对于更大的、有更多 api 调用的系统,我们会被越来越多的来自行为主体的代码弄得混乱不堪。比如:
data1$ = new BehaviorSubject<Data1[]>([]);
data2$ = new BehaviorSubject<Data2[]>([]);
data3$ = new BehaviorSubject<Data3[]>([]);
loading1$ = new BehaviorSubject<boolean>(true);
loading2$ = new BehaviorSubject<boolean>(true);
loading3$ = new BehaviorSubject<boolean>(true);
// and so on
然后我们用某种方法填充数据,比如
this.service.getData1()
.pipe(finalize() => this.loading1$.next(false))
.subscribe(result => this.data1$.next(result);
在更大的模块中,我们有许多这样的方法和许多 BehaviorSubjects
的声明。那么问题来了,有没有办法清理我们的组件呢?因为现在我们可能摆脱了更改检测的手动调用,但我们从行为主体中得到了一些混乱的代码。
我们考虑为行为主体添加一个新的服务。行为主体似乎经常从事其他服务。所以我们最终会得到像
export class BsService {
private data1$ = new BehaviorSubject<Data1[]>([]);
private loading1$ = new BehaviorSubject<boolean>(true);
//... other declarations
getData1Observable$(): Observable<Data1[]> { // this is for async pipe
return this.data1$.asObservable();
}
setData1(data:Data[]){this.data1$.next(data)}
getData1(): Data1[] {return this.data1$.value} //we sometimes need direct access to value
getLoading$(){...}
setLoading(loadin:boolean){...}
pending$() {return combineLatest([...])};
//...and so on
这样的服务,这似乎只清除了 BehaviorSubjects
的声明,也许还有我们与 combineLatest
一起使用的一些方法。设置数据的其余方法将在我们的“智能”组件中保持不变。因此,我们应该将 BsService
添加到组件的构造函数中
constructor(...,service: DataService, behaviorSubjectService: BsService)
(DataService
是组件和 API 服务之间的一层),
这是正确的方法吗?或者也许有更好的方法?
Currently I'm working on some module in which we try to use approach with async pipes
instead of markForCheck
and so on.
Most of data is coming over HTTP, and approach in whole project is to use ChangeDetectionStrategy.OnPush
.
Usualy all ours BehaviourSubjects
are in our 'smart' component and values for presentational components are set by inputs. This was fine for smaller modules. We usualy have 2-6 of such presentation components. For bigger ones, that have more api calls, we get cluttered with more and more code from behaviour subjects. Like:
data1$ = new BehaviorSubject<Data1[]>([]);
data2$ = new BehaviorSubject<Data2[]>([]);
data3$ = new BehaviorSubject<Data3[]>([]);
loading1$ = new BehaviorSubject<boolean>(true);
loading2$ = new BehaviorSubject<boolean>(true);
loading3$ = new BehaviorSubject<boolean>(true);
// and so on
Then we populate it with data in some method like
this.service.getData1()
.pipe(finalize() => this.loading1$.next(false))
.subscribe(result => this.data1$.next(result);
In bigger modules we have many of these method and many of declaration of BehaviorSubjects
. So the question is, is there a way to clear up our component? Because right now maybe we get rid of manual calls for change detection but we get some cluttered code from behaviour subject.
We consider adding a new service for behaviour subject. It seems like often behaviour subjects goes in other service. So we would end up with service like
export class BsService {
private data1$ = new BehaviorSubject<Data1[]>([]);
private loading1$ = new BehaviorSubject<boolean>(true);
//... other declarations
getData1Observable$(): Observable<Data1[]> { // this is for async pipe
return this.data1$.asObservable();
}
setData1(data:Data[]){this.data1$.next(data)}
getData1(): Data1[] {return this.data1$.value} //we sometimes need direct access to value
getLoading$(){...}
setLoading(loadin:boolean){...}
pending$() {return combineLatest([...])};
//...and so on
So this seems to clear only declaration of BehaviorSubjects
, and maybe some methods we use with combineLatest
. Rest of the methods of setting data will stay the same in our 'smart' component. So we should add BsService
to constructor of our component
constructor(...,service: DataService, behaviorSubjectService: BsService)
(DataService
is a layer between component and API service)
Is this correct way of doing this? Or maybe there is better way?
发布评论
评论(1)
每组数据(data1、data2 等)是否都来自 HTTP 调用?您可以摆脱BehaviorSubject并直接使用从HTTP调用返回的数据吗?
例如:
上面是一个 products$ Observable,它提供了产品列表。您不一定需要将其发送到BehaviorSubject 中才能使用它。
如果您需要组合来自多个 HTTP get 的数据以在模板中显示,您可以将这些 Observables 与
combineLatest
组合起来,同样不需要BehaviorSubject。上面的代码组合了一组产品和产品类别,以显示产品及其产品类别名称(而不是存储在产品数据中的 id)。
这样的东西对你有用吗?
Is each set of data (data1, data2, etc) coming from an HTTP call? Can you get rid of the BehaviorSubject and just directly work with the data returned from the HTTP call?
For example:
Above is a products$ Observable that provides the list of products. You don't necessarily need to emit this into a BehaviorSubject to work with it.
And if you need to combine data from multiple HTTP get's for display in a template, you can combine these Observables with
combineLatest
, again without a BehaviorSubject.The above code combines a set of products and product categories to display the products with their product category name (instead of the id stored in the product data).
Would something like that work for you?