如何在 HttpClient Observable 中破坏循环 Angular 16 的 FileList

How to break FileList for loop Angular 16 in HttpClient Observable

提问人:Juan David Luna 提问时间:10/26/2023 更新时间:10/28/2023 访问量:32

问:

我需要在 HttpClient Observable 中的错误情况下中断 FileList FOR 循环。我使用 post 方法发出请求,要求为每个循环迭代上传 1 个文件。这是我的代码,但不起作用,没有中断循环。

        let error = false;
        for (let i = 0; i < this.files.length; i++) {
          const file = this.files.item(i)!;
          this.httpService.importReport(this.report, file, this.code).subscribe({
            error: e => {
              this.httpService.showError(e);
              error = true;
            },
            next: event => {
              const type = event.type;
              if (type==HttpEventType.UploadProgress) {
                const total = event.total!;
                const loaded = event.loaded!;
                this.uploadProgress = loaded / total;
              } else if (type == HttpEventType.Response) {
                console.log(event.body);
              }
            },
            complete: () => {
              this.uploadProgress = 0;
              this.uploadedFiles++;
            }
          });
          if (error) break;
        }

我尝试了带有管道 concatMap 和 catchError 的 try/catch 子句和 throwError,但它不起作用。

角度 循环可 观察到 的中断

评论

0赞 Sudipto Mukherjee 10/26/2023
订阅中的代码是异步代码。因此,当您检查 if(error) 时,订阅代码可能尚未完成其执行,这会导致错误值保持为 false。要么你需要使用aync await来同步执行代码,要么想出一些其他的解决方案
0赞 Juan David Luna 10/26/2023
您知道使用 FOR 循环上传文件的任何替代方案吗?
0赞 Sudipto Mukherjee 10/26/2023
如果服务器端在您的控制之下,为什么不一次性发送整个阵列。如果您使用的节点应该非常简单?或者,当用户上传每个文件时,您可以将它们发送到服务器,而无需等待所有文件。但是,如果这是您想要遵循的方法,我想同步调用是您最好的选择
0赞 MoxxiManagarm 10/26/2023
使用类似 learnrxjs.io/learn-rxjs/operators/combination/concat

答:

0赞 Juan David Luna 10/28/2023 #1

我已经找到了一个没有 FOR 循环的明确解决方案。

async import(file?: File) {
    if (this.files && this.files.length>0) {
      this.uploadedFiles = 0;
      this.loading = true;
      if(!file) file = this.files.item(0)!;
      this.httpService.importReport(this.report, file, this.code).subscribe({
        error: e => {
          this.httpService.showError(e);
          this.files = undefined;
          this.label = 'Ningún archivo seleccionado';
          this.loading = false;
          this.uploadProgress = -1;
          this.error = `File <strong>&laquo; ${file!.name} &raquo;</strong> has an error.`;
        },
        next: event => {
          const type = event.type;
          if (type==HttpEventType.UploadProgress) {
            const total = event.total!;
            const loaded = event.loaded!;
            this.uploadProgress = (loaded / total)*100;
          } else if (type == HttpEventType.Response) {
            console.log(event.body);
          }
        },
        complete: async () => {
          this.okFilenames.push(file!.name);
          this.uploadProgress = -1;
          this.uploadedFiles++;
          if (this.uploadedFiles==this.files!.length) {
            this.loading = false;
            this.message = `¡${this.files!.length} files imported successfully!`;
            this.emitter.emit();
            setTimeout(() => this.modal.dismiss('Cross Click'), 2000);
          } else {
            if (this.report=='teachers') await this.sleep(1000);
            await this.import(this.files!.item(this.uploadedFiles)!);
          }
        }
      });
    } else {
      this.error = 'Please, select at least 1 file.';
      setTimeout(() => {this.error = '';}, 1500);
    }
  }