Skip to content

Commit

Permalink
fix(combineLatest): Fix closure problem with nexts.
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed Aug 21, 2018
1 parent 5b674b7 commit d6296bd
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 16 deletions.
23 changes: 17 additions & 6 deletions source/observable/combineLatestHigherOrder-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ describe("combineLatestHigherOrder", () => {
it("should combine hot observables", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "------c--");
const d = m.hot( "--------d");
const h = m.hot( "i---j--k-", { i: [a, b], j: [a, c], k: [d, c] });
const as = "^------!-";
const bs = "^---!----";
const cs = "----^----";
const ds = "-------^-";
const expected = m.cold( "----x-y-z", { x: ["a", "b"], y: ["a", "c"], z: ["d", "c"] });
const expected = m.cold( "---x--y-z", { x: ["a", "b"], y: ["a", "c"], z: ["d", "c"] });

const combined = h.pipe(combineLatestHigherOrder());
m.expect(combined).toBeObservable(expected);
Expand All @@ -54,14 +54,14 @@ describe("combineLatestHigherOrder", () => {
it("should forward error notifications", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "------#--");
const d = m.hot( "--------d");
const h = m.hot( "i---j--k-", { i: [a, b], j: [a, c], k: [d, c] });
const as = "^-----!--";
const bs = "^---!----";
const cs = "----^-!--";
const expected = m.cold( "----x-#--", { x: ["a", "b"] });
const expected = m.cold( "---x--#--", { x: ["a", "b"] });

const combined = h.pipe(combineLatestHigherOrder());
m.expect(combined).toBeObservable(expected);
Expand Down Expand Up @@ -94,15 +94,15 @@ describe("combineLatestHigherOrder", () => {
it("should not emit later empty sources", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "---------");
const d = m.hot( "---------");
const h = m.hot( "i---j--k-", { i: [a, b], j: [a, c], k: [d, c] });
const as = "^------!-";
const bs = "^---!----";
const cs = "----^----";
const ds = "-------^-";
const expected = m.cold( "----x----", { x: ["a", "b"] });
const expected = m.cold( "---x-----", { x: ["a", "b"] });

const combined = h.pipe(combineLatestHigherOrder());
m.expect(combined).toBeObservable(expected);
Expand Down Expand Up @@ -148,4 +148,15 @@ describe("combineLatestHigherOrder", () => {
m.expect(a).toHaveSubscriptions(as);
m.expect(b).toHaveSubscriptions(bs);
}));

it("should support adds and removes", marbles(m => {

const a = m.cold( "a");
const b = m.cold( "b");
const h = m.hot( "i---j--k-", { i: [a], j: [a, b], k: [b] });
const expected = m.cold( "x---y--z-", { x: ["a"], y: ["a", "b"], z: ["b"] });

const combined = h.pipe(combineLatestHigherOrder());
m.expect(combined).toBeObservable(expected);
}));
});
5 changes: 3 additions & 2 deletions source/observable/combineLatestHigherOrder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ function combine<T>(sources: Source<T>[], observer: Observer<T[]>): void {
export function combineLatestHigherOrder<T>(): OperatorFunction<Observable<T>[], T[]> {
return higherOrder => new Observable<T[]>(observer => {
let lasts: Source<T>[] = [];
let nexts: Source<T>[] = [];
let higherOrderCompleted = false;
const higherOrderSubscription = new Subscription();
higherOrderSubscription.add(higherOrder.subscribe(
observables => {
const subscribes: (() => void)[] = [];
const nexts = observables.map(observable => {
const index = lasts.findIndex(l => l.observable === observable);
nexts = observables.map(observable => {
const index = lasts.findIndex(last => last.observable === observable);
if (index !== -1) {
const next = lasts[index];
lasts.splice(index, 1);
Expand Down
23 changes: 17 additions & 6 deletions source/observable/combineLatestHigherOrderObject-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ describe("combineLatestHigherOrderObject", () => {
it("should combine hot observables", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "------c--");
const d = m.hot( "--------d");
const h = m.hot( "i---j--k-", { i: { a, b }, j: { a, c }, k: { d, c } });
const as = "^------!-";
const bs = "^---!----";
const cs = "----^----";
const ds = "-------^-";
const expected = m.cold( "----x-y-z", { x: { a: "a", b: "b" }, y: { a: "a", c: "c" }, z: { d: "d", c: "c" } });
const expected = m.cold( "---x--y-z", { x: { a: "a", b: "b" }, y: { a: "a", c: "c" }, z: { d: "d", c: "c" } });

const combined = h.pipe(combineLatestHigherOrderObject());
m.expect(combined).toBeObservable(expected);
Expand All @@ -54,14 +54,14 @@ describe("combineLatestHigherOrderObject", () => {
it("should forward error notifications", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "------#--");
const d = m.hot( "--------d");
const h = m.hot( "i---j--k-", { i: { a, b }, j: { a, c }, k: { d, c } });
const as = "^-----!--";
const bs = "^---!----";
const cs = "----^-!--";
const expected = m.cold( "----x-#--", { x: { a: "a", b: "b" } });
const expected = m.cold( "---x--#--", { x: { a: "a", b: "b" } });

const combined = h.pipe(combineLatestHigherOrderObject());
m.expect(combined).toBeObservable(expected);
Expand Down Expand Up @@ -94,15 +94,15 @@ describe("combineLatestHigherOrderObject", () => {
it("should not emit later empty sources", marbles(m => {

const a = m.hot( "--a------");
const b = m.hot( "----b----");
const b = m.hot( "---b-----");
const c = m.hot( "---------");
const d = m.hot( "---------");
const h = m.hot( "i---j--k-", { i: { a, b }, j: { a, c }, k: { d, c } });
const as = "^------!-";
const bs = "^---!----";
const cs = "----^----";
const ds = "-------^-";
const expected = m.cold( "----x----", { x: { a: "a", b: "b" } });
const expected = m.cold( "---x-----", { x: { a: "a", b: "b" } });

const combined = h.pipe(combineLatestHigherOrderObject());
m.expect(combined).toBeObservable(expected);
Expand Down Expand Up @@ -148,4 +148,15 @@ describe("combineLatestHigherOrderObject", () => {
m.expect(a).toHaveSubscriptions(as);
m.expect(b).toHaveSubscriptions(bs);
}));

it("should support adds and removes", marbles(m => {

const a = m.cold( "a");
const b = m.cold( "b");
const h = m.hot( "i---j--k-", { i: { a }, j: { a, b }, k: { b } });
const expected = m.cold( "x---y--z-", { x: { a: "a" }, y: { a: "a", b: "b" }, z: { b: "b" } });

const combined = h.pipe(combineLatestHigherOrderObject());
m.expect(combined).toBeObservable(expected);
}));
});
5 changes: 3 additions & 2 deletions source/observable/combineLatestHigherOrderObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ function combine<T>(sources: Source<T>[], observer: Observer<Record<string, T>>)
export function combineLatestHigherOrderObject<T>(): OperatorFunction<Record<string, Observable<T>>, Record<string, T>> {
return higherOrder => new Observable<Record<string, T>>(observer => {
let lasts: Source<T>[] = [];
let nexts: Source<T>[] = [];
let higherOrderCompleted = false;
const higherOrderSubscription = new Subscription();
higherOrderSubscription.add(higherOrder.subscribe(
observables => {
const subscribes: (() => void)[] = [];
const nexts = Object.keys(observables).map(key => {
nexts = Object.keys(observables).map(key => {
const observable = observables[key];
const index = lasts.findIndex(l => (l.observable === observable) && (l.key === key));
const index = lasts.findIndex(last => (last.observable === observable) && (last.key === key));
if (index !== -1) {
const next = lasts[index];
lasts.splice(index, 1);
Expand Down

0 comments on commit d6296bd

Please sign in to comment.