JavaScript keeping track and association of multiple asynchronious events

Viewed 68

I am writing an Angular 10 application that allows a user to compress and upload images to Google Cloud Storage. The compression and uploading is working fine, however, it's the asynchronous part of associating all concurrent compressions and uploads I am struggling with.

What's the best way to keep track of the current status of compression and upload of each file?

A class variable (e.g. Array of objects) would be ideal to show the progress to the user.

I could push an object to a class Array however how would I keep track of the element to update its status after compression is finished and to set the percentageChanges() observable once the upload has started?

My code looks as follows, processFileList() is called once a user submits the form with selected images in an HTML file input.

 async compressAndUpload(file) {
   // Compress image, function not explained further, returns promise
   const compressed = await compressImage(file);

   // Create path
   const uploadPath: string = 'file' + (new Date()).getTime()
   
   // Upload image
   const imageUploadTask = this.storage.upload(uploadTask, compressed)
   
   // Current percentage of upload can be retrieved as observable
   const percentage = imageUploadTask.percentageChanges()
}


processFileList(fileList: FileList) {
    // Create array from FileList to be able to iterate
    const files = Array.from(fileList);
    
    files.forEach(file => {
        compressAndUpload(file);
    })
   
}
1 Answers

If you want to track progress it's better to use full observable especially if you are in angular framework you should get use to using rxjs:

import { merge, from } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
//...
function compressAndUpload(file) {
   // ... setup uploadTask

  return from(compressImage(file))// preferably convert returned result to observable or cast it using from
    .pipe(
      switchMap((compressed) =>
        this.storage.upload(uploadTask, compressed).percentageChanges()
          .pipe(
            map(progress => ({ file, progress }))
          )
      )
    )
}


function processFileList(fileList: FileList) {
  // Create array from FileList to be able to iterate
  const files = Array.from(fileList);

  return merge([...files.map(compressAndUpload)])
}

processFileList(someFileList)
  // implement your progress reporter on subsciption
  .subscribe(({ file, progress}) => console.log('Progress', progress, 'for file', file))
Related