我将如何总计this.uploads
个可观察变量数组,以便除了每个单独的上载完成百分比之外,还能获得上载的整体百分比?
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$);
}
答案 0 :(得分:3)
可能的解决方案是使用RxJs
combineLatest运算符。查看here以了解其工作原理。
从任何一个观测值发出值时,您需要从所有上载完成值重新计算总完成百分比。
这里是stackblitz演示解决方案。
这是该概念的抽象演示,该概念通过在随机时间间隔内发出0到100之间的值来模拟文件上传。
仅显示个人完成率和总体完成率。
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);
});
}
}