Search code examples
angularrxjs

upload multiple files to the server using RxJs with result of each response coming before next iteration


I am trying to upload multiple files to the server sequentially. Before the next iteration, I want the result of the first iteration. I have tried many solutions with RxJS especially with concatMap with no luck.

I ended up using async method and await each response, before going to the next iteration as shown below. I would be keen to see if it is possible to achieve with purely Rxjs.

private getDocumentData(files: any): void {
    this.myService.getDoc(this.id))
        .pipe(takeUntil(this.destroy$))
        .subscribe(document => {
        this.uploadMultipleFiles(document, files);
    });
}

async updateDoc(document: any, files: any) {
    for (let i = 0; i < files.length; i++) {
        let updatedDocObj = {
            ...document,
            file: {
                date: files[i].lastModified,
                fileName: files[i].name,
            },
        };
        const success = await this.myService.uploadMultipleFiles(
            updatedDocObj,files[i]);
    }
}

Solution

  • here is a rxjs only approach of save data sequentially and use the last data in the next call?

    export class Site7Component {
      private readonly data = [
        { id: 1, name: 'Max', value: 100 },
        { id: 2, name: 'Moritz', value: 200 },
        { id: 3, name: 'Franz', value: 300 },
      ];
    
      ngOnInit(): void {
        from(this.data)
          .pipe(
            concatMap((item) => this.saveData(item)),
            scan((acc, curr) => [...acc, this.doSth(acc, curr)], [] as any[])
          )
          .subscribe((result) => {
            console.log(result);
          });
      }
    
      private saveData(data: any): Observable<any> {
        return new Observable((observer) => {
          //place for the HTTP CALL
          setTimeout(() => {
            observer.next(data);
            observer.complete();
          }, 1000);
        });
      }
    
      private doSth(acc: any[], curr: any): any {
        console.log(acc);
        if (!acc || !acc[acc.length - 1]) {
          return curr;
        }
        return { ...curr, value: curr.value * (acc[acc.length - 1].id + 5) };
      }
    }