如何在Angular 9中将分页与Observable和AsyncPipe结合起来?
有一个来自API的产品列表。产品已分页,用户可以切换到其他页面。简化模板如下所示:如何在Angular 9中将分页与Observable和AsyncPipe结合起来?,angular,asynchronous,rxjs,observable,angular9,Angular,Asynchronous,Rxjs,Observable,Angular9,有一个来自API的产品列表。产品已分页,用户可以切换到其他页面。简化模板如下所示: <ul> <li *ngFor="let product of products$ | async">{{ product.name }}</li> </ul> <button type="button" (click)="gotoPage(1)">1</button> <button type="button" (click)=
<ul>
<li *ngFor="let product of products$ | async">{{ product.name }}</li>
</ul>
<button type="button" (click)="gotoPage(1)">1</button>
<button type="button" (click)="gotoPage(2)">2</button>
export class ProductsComponent implements OnInit {
products$: Observable<Product[]>;
constructor(
private service: ProductService
) { }
ngOnInit() {
this.products$ = this.service.getAll({page: 1});
}
gotoPage(page: number): void {
this.products$ = this.service.getAll({page: page});
}
}
- {{product.name}
1.
2.
该组件确实如下所示:
<ul>
<li *ngFor="let product of products$ | async">{{ product.name }}</li>
</ul>
<button type="button" (click)="gotoPage(1)">1</button>
<button type="button" (click)="gotoPage(2)">2</button>
export class ProductsComponent implements OnInit {
products$: Observable<Product[]>;
constructor(
private service: ProductService
) { }
ngOnInit() {
this.products$ = this.service.getAll({page: 1});
}
gotoPage(page: number): void {
this.products$ = this.service.getAll({page: page});
}
}
导出类ProductsComponent实现OnInit{
产品美元:可观察;
建造师(
私人服务:产品服务
) { }
恩戈尼尼特(){
this.products$=this.service.getAll({page:1});
}
gotoPage(页码):无效{
this.products$=this.service.getAll({page:page});
}
}
我的问题是:
这是更新Obersavble的正确方法吗?或者这会导致内存泄漏
请注意:URL不会更改,并且不应在分页更改时重新加载组件。
您始终可以使用takeUntil+Ngondstroy模式防止内存泄漏 比如说, 声明一个新变量
private onDestroy$:Subject=new Subject()代码>
稍后,在onDestroy()生命周期挂钩中,您可以实现以下功能:
public ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete()
}
我们实际上所做的是宣布一个新的可观察事物;然后,通过对Take使用pipe方法,直到我们通知编译器,当onDestroy$中出现任何值时,我们希望从observable中取消订阅,然后,通过对Take使用pipe方法,直到我们通知编译器,当onDestroy$中出现任何值时,我们希望从observable中取消订阅,因此可以防止内存泄漏。您甚至不订阅您的observable,因此我认为这里不存在可能的内存泄漏,您只需要获取一些数据,异步管道为您处理“转换”
以防万一,当您订阅observable时,您需要添加几行代码以正确地取消订阅并防止内存泄漏:
ngUnsubscribe = new Subject();
myObservable: Observable<any>;
ngOnInit(){
this.myObservable.pipe(takeUntil(ngUnsubscribe))
.subscribe(...)
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
ngUnsubscribe=新主题();
可观察的:可观察的;
恩戈尼尼特(){
这个.myObservable.pipe(takeUntil(ngUnsubscribe))
.订阅(…)
}
恩贡德斯特罗(){
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
一个主题,允许您在每个具有takeUntil
的订阅上触发正确的取消订阅
.next
和complete
是必需的,因为.unsubscribe
不能按预期工作(注意到它与NGRX一起工作,并发现一些stackoverflow线程谈论它)。查看异步管道的内部功能,您可以看到transform()
函数:
if (obj !== this._obj) {
this._dispose();
return this.transform(obj as any);
}
如果有一个,如果它是一个新的对象,它将取消订阅以前的可观察对象。因此,您可以安全地以这种方式使用它。正如我们都知道的,每页的项目数也是如此
我更喜欢将标准更改为行为主题,并使用mergeMap
类产品服务{
构造函数(){
此值为0.defaultCriteria={
页码:0,
页面大小:5
}
}
getAll(标准){
标准={
…这是一个标准,
标准
}
返回rxjs.of(数组(criteria.pageSize).fill(0).map((pr,index)=>{
const num=index+criteria.pageSize*criteria.page+1;
返回{
id:num,
名称:`Product${num}`
}
}))
}
}
类ProductsComponent{
建造师(服务){
服务=服务;
this.page$=新的rxjs.BehaviorSubject(0);
此.products$=null;
}
恩戈尼尼特(){
this.products$=this.page$.asObservable()
.pipe(rxjs.operators.mergeMap(page=>this.service.getAll({
页
})))
}
gotoPage(第页){
此.page$下一页(第页);
}
}
const service=new ProductService();
const component=新产品组件(服务);
组件。ngOnInit();
component.products$.subscribe(products=>console.log(products));
组成部分:gotoPage(1);
组成部分:gotoPage(2)代码>
您还需要this.onDestroy$.complete()
来正确取消订阅。请看下面我的答案谢谢你的回答。如果我需要在组件中订阅,那么与简单的:this.subscription=this.service.getAll().subscripte()在init和destroy中的区别和优势是什么:this.subscription.unsubscripte()代码>?正如我所说,当只使用.unsubscribe()
时,会有一种奇怪的行为,有时无法完全取消订阅您的观察对象。在我的工作中,我有内存泄漏,因为它工作得不好(找不到给我答案的线程,对不起),使用这个apttern解决了我的问题。takeUntil
的优点在于,它只允许您在所有观察到的内容中使用一个主题next&complete
(=取消订阅)。非常感谢。这清楚地表明,它将在转型后取消订阅。