使用 for 循环同步 angular 执行

Synchronize angular execution with for loop

我正在使用 Angular 9 项目,后端为 Spring Boot。该项目基本上是CMS类型的。 在此用户可以使用反应形式生成表格。一个表单可能包含多个文件选择器。我已经实现了在本地路径选择文件和上传文件的代码。

此代码工作正常,但我在同步数据库中实例的保存时遇到问题。

我的流程应该是:

  1. 循环上传文件
  2. 使用上传的数据更新 objectform。
  3. 然后应将具有剩余选项和更新的上传数据的对象形式保存到数据库中。

但是我的流程没有按正确的方式进行,它在上传并且没有等待 return 结果就去保存数据库,所以更新的详细信息没有被保存。

下面是代码流程:

点击保存按钮事件保存表单数据:

saveClick() {
    for (const element of this.objMetaData) {
      if (element.fieldType === 'file-upload') {
        this.uploadAttachment(element.fieldName);
      }
    }
    this.saveToDatabase();
  }

这应该在最后保存更新的详细信息:

saveToDatabase() {
    let relations = [];
    const instanceBody = {
      objectTypeId: this.objectTypeId,
      objectInstance: {...this.objectFormGroup.value, relations: relations}
    }
    this.saveInstance(instanceBody);
  }

正在上传文件并更新对象以保存数据:

uploadAttachment(fieldName: string) {
    let formData = new FormData();
    let fileObj: any = this.fileMap.get(fieldName);
    let fileName = fileObj.name;
    if (fileObj !== undefined) {
      formData.append('file', fileObj);
      this.attachmentService.uploadAttachment(formData).subscribe((result) => {
        if (result != null) {
          let attachmentDir = result;
          let attachmentFileName = fileName;
          let attachment = attachmentDir + '**' + attachmentFileName;
          this.objectFormGroup.value[fieldName] = attachment;             
        } else {              
          console.log("File not uploaded.")
        }
      });
    }
  }

代码流程不顺。

this.saveToDatabase();

这是在 for 循环中上传之前调用的。我已经尝试了很多东西,比如将 forEach 更新为 for loop、async、await 等,但效果不佳。

如何解决使执行同步的问题。

要解决这个问题,这里的方法是使用Rxjs. Get all Observables from the uploadAttachment function and combine them with combinelatest。然后订阅这个组合挂钩到 运行 saveToDatabase 仅当所有调用都已 returned.

在代码中它会呈现类似

的东西
saveClick() {
    let observables: Observable<any>[] = [];
    for (const element of this.objMetaData) {
          if (element.fieldType === 'file-upload') {
            let uploadObservable = this.uploadAttachment(element.fieldName);
            if(uploadObservable) observables.push(uploadObservable);
          }
    }
    combineLatest(observables)
    .pipe(take(1))
    .toPromise()
    .then(()=>{ 
        this.saveToDatabase();
    });
}

同样为了让这个工作正常,我们需要 uploadAttachment 函数到 return 上传可观察对象。

uploadAttachment(fieldName: string): Observable<any> {
    // ... 
    return this.attachmentService.uploadAttachment(formData)
    .pipe(tap(result=>{ 
        // ... Callback code goes here 
    }));
}

注意我正在使用 Rxjs 运算符管道,拿走并点击。

如果你还不知道,我相信你真的应该看看 angular 网站上关于 rxjs 的 here. There's also an article

编辑:添加了 stackblitz demo