class Observable {
constructor(producer) {
this.subscribe = producer
}
}
Observable.prototype.of = function (...values) {
const producer = observer => {
values.forEach(v => observer.next(v));
observer.complete();
}
return new Observable(producer)
}
Observable.prototype.delay = function (time) {
const producer = observer => {
return this.subscribe({
next(value) {
setTimeout(() => observer.next(value), time)
},
complete() {
setTimeout(() => observer.complete(), time)
}
})
};
return new Observable(producer);
}
Observable.prototype.switchMap = function (f) {
const producer = outObserver => {
let i = 0;
let hasSourceCompleted = false;
const completed = [];
this.subscribe({
next: (x) => {
i++;
completed[i] = false;
f(x).subscribe({
next: ((index, y) => {
if (index === i) {
outObserver.next(y)
}
}).bind(this, i),
complete: ((index) => {
completed[index] = true;
if (hasSourceCompleted && completed.every(x => x)) outObserver.complete();
}).bind(this, i),
});
},
complete: (() => {
hasSourceCompleted = true;
if (hasSourceCompleted && completed.every(x => x)) outObserver.complete();
}),
});
};
return new Observable(producer);
};
const observer = {
next(value) { console.log(value) },
complete() { console.log('Done') }
}
new Observable().of(1, 2).switchMap((v) => {
if (v === 1) return new Observable().of(v).delay(400)
if (v === 2) return new Observable().of(v).delay(200)
}).subscribe(observer);