Angular Typescript RXJS: Issues with Chaining Observables Using SwitchMap and ForkJoin

After the console logs finish, my forkjoin is triggered. To solve this issue, instead of returning empty() or of(), you can return an empty object as an observable. This way, Forkjoin still maintains value, so return of({}) and everything will be fine.
I am searching for a method to perform an action after all controls on a page are loaded. The method can only accept an array of observables, execute them in parallel, and then wait for all of them to complete before emitting the resultant values.


Question:

My current objective is to establish a system that triggers three observables in a forkjoin when I successfully update a request. After the observables are finished, the console should log ‘complete/or finish’. However, if the update is unsuccessful, nothing should happen. Currently, I am encountering a problem where the observables are finishing before the forkjoin is complete, and I am unsure of the cause of this issue.

  copyAttachments(): Observable {
    if (this.model.attachments.length > 0) {
      return this.attachmentService.copyAttachments(this.model.attachments, this.model.id);
    }
    return empty();
  }

  uploadAttachments(): Observable {
    this.showAttachmentsUploadingModal = true;
    const formData = new FormData();

    if (this.formAttachments.length > 0) {
      this.showAttachmentsUploadingModal = true;
      this.formAttachments.forEach(file => {
        formData.append('files', file, file.name);
      });
    }

    // uploading empty formData will still trigger creation of default folder structure
    return this.attachmentService.uploadAttachments(formData, this.model.id);
  }

  uploadCustomerData(): Observable {
    this.showAttachmentsUploadingModal = true;
    const formData = new FormData();

    if (this.formCustomerData.length > 0) {
      this.showAttachmentsUploadingModal = true;
      this.formCustomerData.forEach(file => {
        formData.append('files', file, file.name);
      });
      return this.attachmentService.uploadCustomerData(formData, this.model.id);
    }

    return empty();
  }
handleAttachments(): Observable {
    return forkJoin
      (
        this.copyAttachments(),
        this.uploadCustomerData(),
        this.uploadAttachments()
      )
  }

  updateRequest() {
    this.myservice
      .updateRequest(this.model)
      .pipe(
        switchMap((saveResult: boolean) => {
          this.showSubmittingModal = false;
          if (saveResult === true) {
            return this.handleAttachments();
          } else {
            return empty();
          }
        }),
      )
      .pipe(finalize(() => {
        console.log('finish')
      }))
      .subscribe(
        response => {
          // todo: do anything with this response from uploadAttachments()?
          this.showAttachmentsUploadingModal = false;
        },
        error => {
          location.reload();
        },
        () => {
          console.log('complete')
        }
      );
  }

Upon successful completion of both my service and forkjoin observables, the console will log ‘finish’.

At present, the service finishes and outputs ‘finish’ through console.log, which in turn activates my forkjoin.


Solution:

Instead of using empty() or of() to solve this problem, you can return an empty object as an observable. This approach will ensure that Forkjoin retains its value. Therefore, returning of({}) will resolve the issue.

Frequently Asked Questions