// waits for all Observables no matter of success/fails each of them
// returns array of items
// each item represent even first value of Observable or it's error
export function waitAll(args: Observable<any>[]): Observable<any[]> {
const final = new Subject<any[]>();
const flags = new Array(args.length);
const result = new Array(args.length);
let total = args.length;
for (let i = 0; i < args.length; i++) {
flags[i] = false;
args[i].subscribe(
res => {
console.info('waitAll ' + i + ' ok ', res);
if (flags[i] === false) {
flags[i] = true;
result[i] = res;
total--;
if (total < 1) {
final.next(result);
}
}
},
error => {
console.error('waitAll ' + i + ' failed ', error);
if (flags[i] === false) {
flags[i] = true;
result[i] = error;
total--;
if (total < 1) {
final.next(result);
}
}
}
);
}
return final.asObservable();
}
单元测试:
describe('waitAll', () => {
it('should wait for all observables', async () => {
const o1 = new Subject();
const o2 = new Subject();
const o3 = new Subject();
const o = waitAll([o1, o2, o3]);
const res = {arr: []};
o.subscribe(result => res.arr = result, err => res.arr = []);
expect(res.arr).toEqual([]);
o1.next('success1');
expect(res.arr).toEqual([]);
o2.error('failed2')
expect(res.arr).toEqual([]);
o3.next('success3')
expect(res.arr).toEqual(['success1', 'failed2', 'success3']);
o1.next('success1*');
expect(res.arr).toEqual(['success1', 'failed2', 'success3']);
o2.error('failed2*')
expect(res.arr).toEqual(['success1', 'failed2', 'success3']);
o3.next('success3*')
expect(res.arr).toEqual(['success1', 'failed2', 'success3']);
});
});