Skip to content

Commit

Permalink
fix(RouterInstruction): Pass the subscriber back through NgZone (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeRyanDev authored and brandonroberts committed Apr 26, 2016
1 parent e6a2920 commit 894b088
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 7 deletions.
11 changes: 7 additions & 4 deletions lib/router-instruction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import 'rxjs/add/operator/let';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/observeOn';
import { Observable } from 'rxjs/Observable';
import { async } from 'rxjs/scheduler/async';
import { provide, Provider, Injector, OpaqueToken } from 'angular2/core';
import { asap } from 'rxjs/scheduler/asap';
import { provide, Provider, Injector, OpaqueToken, NgZone } from 'angular2/core';
import { parse as parseQueryString } from 'query-string';

import { ZoneOperator } from './zone';
import { compose } from './util';
import { Router, LocationChange } from './router';
import { Routes, Route, ROUTES } from './route';
Expand Down Expand Up @@ -47,13 +48,14 @@ export class RouterInstruction extends Observable<NextInstruction> { }


function createRouterInstruction(
zone: NgZone,
router$: Router,
traverser: RouteTraverser,
locationMiddleware: Middleware[],
routerInstructionMiddleware: Middleware[]
): RouterInstruction {
return router$
.observeOn(async)
.observeOn(asap)
.distinctUntilChanged((prev, next) => prev.path === next.path)
.let<LocationChange>(compose(...locationMiddleware))
.switchMap(change => {
Expand All @@ -71,14 +73,15 @@ function createRouterInstruction(
})
.filter(match => !!match)
.let<NextInstruction>(compose(...routerInstructionMiddleware))
.lift(new ZoneOperator(zone))
.publishReplay(1)
.refCount();
}


export const ROUTE_SET_PROVIDERS = [
provide(RouterInstruction, {
deps: [ Router, RouteTraverser, ROUTER_MIDDLEWARE, ROUTER_INSTRUCTION_MIDDLEWARE ],
deps: [ NgZone, Router, RouteTraverser, ROUTER_MIDDLEWARE, ROUTER_INSTRUCTION_MIDDLEWARE ],
useFactory: createRouterInstruction
}),
useRouterMiddleware(identity),
Expand Down
22 changes: 22 additions & 0 deletions lib/zone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NgZone } from 'angular2/core';
import { Operator } from 'rxjs/Operator';
import { Subscriber } from 'rxjs/Subscriber';


export class ZoneOperator<T> implements Operator<T, T> {
constructor(private _zone: NgZone) { }

call(subscriber: Subscriber<T>): Subscriber<T> {
return new ZoneSubscriber(subscriber, this._zone);
}
}

class ZoneSubscriber<T> extends Subscriber<T> {
constructor(destination: Subscriber<T>, private _zone: NgZone) {
super(destination);
}

protected _next(value: T) {
this._zone.run(() => this.destination.next(value));
}
}
23 changes: 21 additions & 2 deletions spec/route-set.spec.ts → spec/router-instruction.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'rxjs/add/operator/withLatestFrom';
import { Injector, provide } from 'angular2/core';
import { Injector, provide, NgZone } from 'angular2/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { LocationStrategy } from 'angular2/src/router/location/location_strategy';
Expand All @@ -15,6 +15,7 @@ describe('Route Set', function() {
const routes = ['a', 'c', 'c'];

let mockTraverser: any;
let mockZone: any;
let routerInstruction: RouterInstruction;
let router: Router;

Expand All @@ -25,13 +26,21 @@ describe('Route Set', function() {
}
};

mockZone = {
run(fn) {
return fn();
}
};

spyOn(mockTraverser, 'find').and.callThrough();
spyOn(mockZone, 'run').and.callThrough();

const injector = Injector.resolveAndCreate([
ROUTER_PROVIDERS,
ROUTE_SET_PROVIDERS,
provide(RouteTraverser, { useValue: mockTraverser }),
provide(LocationStrategy, { useClass: MockLocationStrategy })
provide(LocationStrategy, { useClass: MockLocationStrategy }),
provide(NgZone, { useValue: mockZone })
]);

routerInstruction = injector.get(RouterInstruction);
Expand Down Expand Up @@ -75,4 +84,14 @@ describe('Route Set', function() {
done();
});
});

it('should pass the subscription back into the Angular zone', function(done) {
router.go('/');

routerInstruction.subscribe(() => {
expect(mockZone.run).toHaveBeenCalled();

done();
});
});
});
2 changes: 1 addition & 1 deletion spec/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"./middleware.spec.ts",
"./params.spec.ts",
"./redirect.spec.ts",
"./route-set.spec.ts",
"./router-instruction.spec.ts",
"./route-traverser.spec.ts",
"./route-view.spec.ts",
"./route.spec.ts",
Expand Down

0 comments on commit 894b088

Please sign in to comment.