1

How would I total up this.uploads array of observables so that I can get the overall percentage of the upload in addition to each individual upload completion percentage?

uploadFile(event) {
    // reset the array 
    const filelist = event.target.files;
    const allPercentage: Observable<number>[] = [];
    for (var i = 0; i < filelist.length; i++) {
      const file = filelist[i];
      const filePath = `${file.name}`;
      const fileRef = this.storage.ref(filePath);
      const task = this.storage.upload(filePath, file);
      const _percentage$ = task.percentageChanges();
      this.uploads[i] = _percentage$;
      this.totalPercentage.push(_percentage$);
  }
2
  • Is it an array of Observables, or an Observable that emits an array? Commented Nov 8, 2018 at 13:38
  • any array of observables Commented Nov 8, 2018 at 15:30

1 Answer 1

4

A possible solution is to use RxJs combineLatest operator. Look here to understand how it works.
When a value is emitted from any of the observables, you need to recalculate the overall completion percentage from all uploads completions values.

Here is a stackblitz demonstrating the solution.
This is an abstract demonstration of the concept which simulates file upload by emitting values between 0 and 100 at random time interval.
Individual and overall completion percentages are simply displayed.

import { Component } from '@angular/core';
import { combineLatest, Observable } from 'rxjs';

@Component({
  selector: 'my-app',
  template: `
    <ul>
      <li *ngFor="let observable of observables; let i = index">observable {{i + 1}}: {{observable | async}}</li>
    </ul>
    <p>total = {{total}}</p>`,
})
export class AppComponent {
  private readonly OBSERVABLES_COUNT = 10;

  total = 0;
  observables: Observable<number>[] = [];

  constructor() {
    // create observables
    for (let i = 0; i < this.OBSERVABLES_COUNT; i++) {
      this.observables.push(this.createObservable());
    }

    // listen to combined streams
    combineLatest(this.observables).subscribe(values => {
      // when a value is emited from any of the streams, recalculate total
      let total = 0;
      // sum values
      values.forEach(value => total += value);
      // divide by observables count to get average
      total /= this.OBSERVABLES_COUNT;
      // display total
      this.total = total;
    });
  }

  /**
   * This creates an observable roughly simulating a file upload.
   * Values are emitted at a constant random time interval from 0 to 100.
   */
  createObservable(): Observable<number> {
    // create observable
    return Observable.create(observer => {
      // init value
      let value = 0;
      // init interval
      const interval = setInterval(
        () => {
          // increment value
          value += 10;
          // emit it
          observer.next(value);
          // stop when value reaches 100
          if (value === 100) {
            // complete observable
            observer.complete();
          }
        },
        // set a random time interval
        Math.random() * 1000,
      );
      // start with 0
      observer.next(0);
    });
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.