Angular 6等待可观察

时间:2018-11-28 20:09:01

标签: angular

我有以下打字稿代码。

我试图使packageFiles方法成为可观察的,所以我可以等到完成后再继续。但是有什么不对吗?

packageFiles(): Observable<any> {

  var filesToSend = [];

  //Loop through files
  this.files.forEach(f => {
    var reader = new FileReader();
    reader.onload = (e) => {
      //
      var fileForUpload = new FileForUpload();
      var encodedString = window.btoa(<string>reader.result);
      fileForUpload.FileValue = encodedString;
      fileForUpload.FileName = f.name;
      fileForUpload.FileType = f.type;

      //
      filesToSend.push(fileForUpload);

      console.log(filesToSend);
    };

    reader.readAsDataURL(f);

  });

  return of(filesToSend);
}

此方法随后将其调用:

uploadFiles() {

  var response = this.packageFiles()
  .subscribe(
    data => {
      console.log("data");
      console.log(data);
    },
    error => {

    }
  );
}

2 个答案:

答案 0 :(得分:0)

在调用filesToSend时,您将插入reader.onload,而在遍历文件时不会发生这种情况。自然,在通过filesToSend构造可观察对象时,您的of是一个空数组。调用订阅将直接导致主题发出空数组。

相反,您应该创建一个主题,每次加载完成后都调用next()

答案 1 :(得分:0)

您正在此处同步返回一个可观察到的空数组,这不是您想要执行的操作。您需要确保首先收集数据,然后在可观察的位置发射(of立即发射然后完成)。

让我们假设您只有一个file。在这种情况下,最接近您的代码的地方将使用Subject

packageFiles(): Observable<FileForUpload> {
  const result$ = new Subject<FileForUpload>();
  const reader = new FileReader();
  reader.onload = () => {
    const fileForUpload = new FileForUpload();
    // … do your stuff …

    result$.next(fileForUpload);
    result$.complete();
  };

  // …

  return result$;
}

但是,这将返回一个热的可观测值,最好在这里返回一个冷的可观测值:

packageFiles(): Observable<FileForUpload> {
  return Observable.create(observer => {
    const reader = new FileReader();
    reader.onload = () => {
      const fileForUpload = new FileForUpload();
      // … do your stuff …

      observer.next(fileForUpload);
      observer.complete();
    };

    // …
  });
}

现在,您只需要将其概括为多个文件即可。让我们将其重命名为packageFile并将文件作为输入传递:

packageFile(file: File): Observable<FileForUpload> {
  // …
}

然后我们可以将实际函数编写为

packageFiles(): Observable<FileForUpload[]> {
  return forkJoin(...this.files.map(file => this.packageFile(file)));
}

…现在可以通过致电使用

this.packageFiles().subscribe(filesToUpload => { /* … */ });