Skip to content

Commit

Permalink
fix(auth): add scheduler to schedule onAuth events through Angular zone
Browse files Browse the repository at this point in the history
Closes #354
  • Loading branch information
jeffbcross committed Jul 22, 2016
1 parent 9edf33a commit 1778ed3
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 6 deletions.
23 changes: 23 additions & 0 deletions src/auth/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ const AngularFireAuthState = <FirebaseAuthState>{
}
};

describe('Zones', () => {
it('should call operators and subscriber in the same zone as when service was initialized', (done) => {
// Initialize the app outside of the zone, to mimick real life behavior.
var app = initializeApp(COMMON_CONFIG, 'zoneapp');

let ngZone = Zone.current.fork({
name: 'ngZone'
});
ngZone.run(() => {
var afAuth = new AngularFireAuth(new FirebaseSdkAuthBackend(app), window.location);
afAuth
.take(1)
.do(_ => {
expect(Zone.current.name).toBe('ngZone');
})
.subscribe(() => {
expect(Zone.current.name).toBe('ngZone');
done()
}, done.fail);
});
});
});

describe('FirebaseAuth', () => {
let app: firebase.app.App;
let authData: any;
Expand Down
13 changes: 10 additions & 3 deletions src/auth/firebase_sdk_auth_backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Injectable, Inject } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { FirebaseApp } from '../tokens';
import { isPresent } from '../utils';
import { isPresent, ZoneScheduler } from '../utils';
import { auth } from 'firebase';
import {
authDataToAuthState,
Expand All @@ -22,6 +22,7 @@ const {

import 'rxjs/add/operator/map';
import 'rxjs/add/observable/fromPromise';
import 'rxjs/add/operator/observeOn';

@Injectable()
export class FirebaseSdkAuthBackend extends AuthBackend {
Expand All @@ -42,14 +43,20 @@ export class FirebaseSdkAuthBackend extends AuthBackend {
}

onAuth(): Observable<FirebaseAuthState> {
// TODO: assumes this will accept an RxJS observer
return Observable.create((observer: Observer<FirebaseAuthState>) => {
return this._fbAuth.onAuthStateChanged(observer);
})
.map((user: firebase.User) => {
if (!user) return null;
return authDataToAuthState(user);
});
})
/**
* TODO: since the auth service automatically subscribes to this before
* any user, it will run in the Angular zone, instead of the subscription
* zone. The auth service should be refactored to capture the subscription
* zone and not use a ReplaySubject.
**/
.observeOn(new ZoneScheduler(Zone.current));
}

unauth(): void {
Expand Down
22 changes: 21 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Subscription } from 'rxjs/Subscription';
import { QueueScheduler } from 'rxjs/scheduler/QueueScheduler';
import { Scheduler } from 'rxjs/Scheduler';
import { AFUnwrappedDataSnapshot} from './interfaces';

export function isPresent(obj: any): boolean {
Expand Down Expand Up @@ -75,4 +78,21 @@ export function stripLeadingSlash(value: string): string {
} else {
return value;
}
}
}

/**
* TODO: remove this scheduler once Rx has a more robust story for working
* with zones.
*/
export class ZoneScheduler extends QueueScheduler {
constructor(public zone?: Zone) {
super();
}

schedule(...args): Subscription {
if (!this.zone) {
throw new Error('ZoneScheduler.schedule was called before a zone was set');
}
return <Subscription>this.zone.run(() => super.schedule.apply(this, args));
}
}
7 changes: 6 additions & 1 deletion test/e2e/auth/firebase_auth_example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
FirebaseApp
} from '../../../dist/angularfire2';

declare var Zone: any;

enableProdMode();

// TODO fix imports and tsconfig
Expand Down Expand Up @@ -111,7 +113,10 @@ class App {
auth: null // makes easier to convert to json
})
})
.subscribe(user => this.user = user);
.subscribe(user => {
console.log('zone', Zone.current.name);
this.user = user
});
}

signInAnonymously() {
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"src/auth/auth.spec.ts",
"src/auth/auth_backend.spec.ts",
"typings/main.d.ts",
"manual_typings/firebase3/firebase3.d.ts"
"manual_typings/firebase3/firebase3.d.ts",
"node_modules/zone.js/dist/zone.js.d.ts"
]
}

0 comments on commit 1778ed3

Please sign in to comment.