【问题标题】:Angular: How to get async data for templateAngular:如何获取模板的异步数据
【发布时间】:2020-08-10 16:25:27
【问题描述】:

我有以下问题:

我想制作一个包含条目(Obj)的表格。其中一些具有文件属性。 如果他们有文件属性(entry.file),我想进行后端调用以获取该文件的 url:

public getFileURL(archiveID: string, documentID: string, sysID: string){
    const request: FileRequest = {
      archiveID: archiveID,
      documentID: documentID,
      sysID: sysID
    };
    this.fileService.file(request).subscribe(response => {
      if (response) {
        return response;
      }
    })
}

这被称为:getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID) 它应该返回一个 Observable,所以我可以检查我是否得到了后端响应。

<tr *ngFor="let entry of period.claims; let i = index">
...
<td>
  <div *ngIf="entry.file">
    <div *ngIf="fileClientService.getFileURL(entry.file.archiveID, entry.file.documentID, entry.file.sysID) | async as file; else loading">
      <a target="about:blank" class="download" (click)="clickLink(file)"></a>
    </div>
    <ng-template #loading let-file>loading..</ng-template>
  </div>
</td>

我想要的只是显示“正在加载”,直到加载 url,然后显示 a-tag。 此外,从后端返回的 url 参数可能为空。因此,如果 url 为空(“”),我也不需要显示任何内容。 目前,它会触发数百个后端调用,调用 2 个具有 entry.file 属性的对象:(

我对 Observables 不太擅长,我希望有人可以帮助我。 到目前为止谢谢你:)

【问题讨论】:

  • 你在上面的代码中遇到了什么问题?
  • 我强烈建议事先使用 switchMap 将文件对象映射到 url。
  • 它每分钟产生数百个后端调用。但它应该每个 URL 只调用一次。

标签: html angular typescript rxjs


【解决方案1】:

您需要直接从您的方法中返回 Observable 并将您的 period.claims 映射到一个 Observable:

// add proper type
entries: Observable<...> = getEntries();

getEntries() {
  // we map every claim to Observable returned from getFileURL method
  const entries = period.claims.map(entry => 
    getFileURL(...).pipe(
      // we use map to return whole entry from Observable - not only url
      map(url => ({
        ...entry,
        url,
      }))
  ));
  // forkJoin will return one Observable with value array when each Observable is completed
  return forkJoin(...entries);
}

public getFileURL(archiveID: string, documentID: string, sysID: string): Observable<...> {
    const request: FileRequest = {
      archiveID: archiveID,
      documentID: documentID,
      sysID: sysID
    };
    return this.fileService.file(request).pipe(filter(Boolean));
}

如果您不想传递给模板空响应,您可以使用 filter 运算符并将布尔值作为回调传递。它只会返回真实值。您可以阅读更多相关信息:https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter 您还可以阅读有关forkJoin 的更多信息:https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

请注意,为方法添加正确的类型会告诉你你做错了什么;)

【讨论】:

  • 这也调用了后端数百次。你为什么使用 Observable ? fileService.file() 的返回是 {url: "url"}
  • 我也不理解'as file'属性。这是否意味着我可以使用 ngIf 的返回值?比如:当 getFileURL() 返回一个值时,我可以使用这个返回作为文件吗? (例如 file.url)
  • 添加属性 fileUrl 并在模板中使用它以避免多个方法调用 - 我已经编辑了答案。类型文件可以是任何东西。这只是一个例子。
  • 我会这样做,但我可以有多个 fileURL。如果我只有一个,我可以将它与 fileUrl = getFileURL(...);然后是 this.fileURL。我需要建立一个数组来保留更多的fileURL吗?
  • 你的意思是 API 可以返回多个 url?或者你的意思是你需要每个entry 的url?我会映射 period.claims 并将其设为 Observable。
猜你喜欢
  • 1970-01-01
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 2013-08-02
相关资源
最近更新 更多