如何在Angular 9中将分页与Observable和AsyncPipe结合起来?

如何在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)=

有一个来自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)="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
(=取消订阅)。非常感谢。这清楚地表明,它将在转型后取消订阅。