Angular 项目的NGF内部异步管道

Angular 项目的NGF内部异步管道,angular,Angular,如何在ngFor内部使用AsyncPipe,或者实现对列表项的异步调用的最佳实践是什么 示例: 假设我有一个产品订单,我想显示产品的制造商。但制造商需要从存储器(localstorage)加载才能显示。我最初的解决方案是以下(未经测试的伪代码): HTML: 当然,这会导致无休止的循环 我的下一个解决方案是,检查ngOnInit中的所有订单及其所有产品,找到制造商,并将其存储在地图中以供以后在表达式中使用 我觉得应该有一个更好的解决方案——因为这还没有结束:我还必须实施DoCheck,以检查是否

如何在
ngFor
内部使用
AsyncPipe
,或者实现对列表项的异步调用的最佳实践是什么

示例: 假设我有一个产品订单,我想显示产品的制造商。但制造商需要从存储器(localstorage)加载才能显示。我最初的解决方案是以下(未经测试的伪代码):

HTML:

当然,这会导致无休止的循环

我的下一个解决方案是,检查
ngOnInit
中的所有订单及其所有产品,找到制造商,并将其存储在
地图中
以供以后在表达式中使用


我觉得应该有一个更好的解决方案——因为这还没有结束:我还必须实施
DoCheck
,以检查是否有任何产品阵列或制造商更改并重新加载所述地图。这适用于每个类似引用的字段。

您可以获得以下产品:

products$ = this.myService.getProducts();
manufacturersAndProducts$ = this.products$.pipe(
  switchMap(products => forkJoin(products
    .map(product => this.myService.getManufacturerForProduct(product))
  )).pipe(
    map(manufacturers => products
      .map((product, index) => ({ product, manufacturer: manufacturers[index] }))
    )
  )
);
然后是制造商,并将他们加入到产品中:

products$ = this.myService.getProducts();
manufacturersAndProducts$ = this.products$.pipe(
  switchMap(products => forkJoin(products
    .map(product => this.myService.getManufacturerForProduct(product))
  )).pipe(
    map(manufacturers => products
      .map((product, index) => ({ product, manufacturer: manufacturers[index] }))
    )
  )
);
然后将其用于HTML

<ng-container *ngIf="manufacturersAndProducts$ | async as list">
  <div *ngFor="let item of list">
    {{ item.product.name }} is made by {{ item.manufacturer.name }}
  </div>
</ng-container>

{{item.product.name}}由{{item.manufacturer.name}制作
但这是一个糟糕的例子,因为对于HTTP调用,您并不真正需要这种反应式编程。例如,当产品列表每10秒左右更改一次时,它非常有用

为了回答您的疑问,您的问题是断章取义的:它不应该是关于异步的,而是关于模板的良好实践

您不应该在模板中使用不纯净的函数(具有副作用的函数),否则,正如您所说的,您的视图会再次渲染,从而导致无限循环,或者最多导致性能问题


您应该使用纯函数,或者使用其中的所有数据构造一个完整的对象(就像我在这里所做的,但您不需要异步管道)

您可以得到以下产品:

products$ = this.myService.getProducts();
manufacturersAndProducts$ = this.products$.pipe(
  switchMap(products => forkJoin(products
    .map(product => this.myService.getManufacturerForProduct(product))
  )).pipe(
    map(manufacturers => products
      .map((product, index) => ({ product, manufacturer: manufacturers[index] }))
    )
  )
);
然后是制造商,并将他们加入到产品中:

products$ = this.myService.getProducts();
manufacturersAndProducts$ = this.products$.pipe(
  switchMap(products => forkJoin(products
    .map(product => this.myService.getManufacturerForProduct(product))
  )).pipe(
    map(manufacturers => products
      .map((product, index) => ({ product, manufacturer: manufacturers[index] }))
    )
  )
);
然后将其用于HTML

<ng-container *ngIf="manufacturersAndProducts$ | async as list">
  <div *ngFor="let item of list">
    {{ item.product.name }} is made by {{ item.manufacturer.name }}
  </div>
</ng-container>

{{item.product.name}}由{{item.manufacturer.name}制作
但这是一个糟糕的例子,因为对于HTTP调用,您并不真正需要这种反应式编程。例如,当产品列表每10秒左右更改一次时,它非常有用

为了回答您的疑问,您的问题是断章取义的:它不应该是关于异步的,而是关于模板的良好实践

您不应该在模板中使用不纯净的函数(具有副作用的函数),否则,正如您所说的,您的视图会再次渲染,从而导致无限循环,或者最多导致性能问题


您应该使用纯函数,或者构造一个包含所有数据的完整对象(就像我在这里所做的,但您不需要异步管道)

在显示之前,您不需要使用async/wait或加载所有数据。在
产品
类型中添加一个字段,并指定一个承诺或一个可观察到的内容,以解析所需数据

服务

Load(id: any): any {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`Manufacturer id [${id}], name, address`);
        }, Math.random() * 5000 + 2000);
    });
}
组成部分

ngOnInit() {
    for (let i = 1; i < 10; i++) {
        this.order.toProducts.push(
            { Name: 'ProdName' + i, manufacturerId: i, data: this.storageService.Load('manufacturerId#' + i) },
        );
    }
}
ngOnInit(){
for(设i=1;i<10;i++){
这个.order.toProducts.push(
{Name:'ProdName'+i,manufacturerId:i,data:this.storageService.Load('manufacturerId#'+i)},
);
}
}
模板

<ol>
  <li *ngFor="let prod of order.toProducts">
    {{ prod.Name }}: {{ prod.data | async }}
  </li>
<ol>


{{prod.Name}:{{prod.data | async}


完整的工作示例:

在显示数据之前,不需要使用异步/等待或加载所有数据。在
产品
类型中添加一个字段,并指定一个承诺或一个可观察到的内容,以解析所需数据

服务

Load(id: any): any {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(`Manufacturer id [${id}], name, address`);
        }, Math.random() * 5000 + 2000);
    });
}
组成部分

ngOnInit() {
    for (let i = 1; i < 10; i++) {
        this.order.toProducts.push(
            { Name: 'ProdName' + i, manufacturerId: i, data: this.storageService.Load('manufacturerId#' + i) },
        );
    }
}
ngOnInit(){
for(设i=1;i<10;i++){
这个.order.toProducts.push(
{Name:'ProdName'+i,manufacturerId:i,data:this.storageService.Load('manufacturerId#'+i)},
);
}
}
模板

<ol>
  <li *ngFor="let prod of order.toProducts">
    {{ prod.Name }}: {{ prod.data | async }}
  </li>
<ol>


{{prod.Name}:{{prod.data | async}


完整的工作示例:

您可以使用一个布尔变量(默认为false),该变量在分配数据时变为true。在html just do
中,我不明白此注释与问题(?)^^有何关系,该问题建议仅在发生异步事件时显示基于布尔值的内容,并将布尔值设置为true。使用*ngIf决定是否显示内容。问题不是关于“一个”异步事件,而是关于许多异步事件,并且不知道它们何时以及如何发生。您可以使用一个布尔变量(默认为false),该变量在分配数据时变为true。在html just do
中,我不明白此注释与问题(?)^^有何关系,该问题建议仅在发生异步事件时显示基于布尔值的内容,并将布尔值设置为true。使用*ngIf决定是否显示内容。问题不是关于“一个”异步事件,而是关于许多异步事件,不知道它们应该在何时以及如何发生。