2

I am quite new to angular2 but i tried to write a login component. Everything works fine except after a successful login i want to set the username and password in my session service (where i store the username and password to create basic auth headers). Sadly this._session.loggedIn never gets set. Anybody an idea why?

export class LoginComponent {

    public email = '';
    public password = '';

    constructor(
        private _router: Router,
        private _auth: AuthenticationService,
        private _session: SessionService) {
    }

    login() {
        this._auth.login(this.email, this.password)
            .subscribe(
                data => {
                    this._session.currentProfile = data;
                    this._session.loggedIn = true;
                    this._router.navigate(['Home']);
                },
                err => {}
            );
    }
}

AuthenticationService:

login(email, password){
        return this._http.get('/profile')
            .map(res => res.json());
}
2
  • What is the login() method? When it should be invoked? If you subscribe, it does not dynamically dispatch an event. Commented Sep 9, 2016 at 7:26
  • @KamilMyśliwiec i added the login method. just a simple http get. it get´s invoked on button press. The only problem is that in the subscribe callback the data doesn´t get set in the session service Commented Sep 9, 2016 at 7:29

1 Answer 1

2

This code is a function passed to subscribe

        data => {
            this._session.currentProfile = data;
            this._session.loggedIn = true;
            this._router.navigate(['Home']);
        }

This code is not executed immediately but sometimes later, when the response from the server arrives or whatever event is necessary for the observable to emit a new event which then causes above function to be called.

This means

login() {
    this._auth.login(this.email, this.password)
        .subscribe(
            data => {
                this._session.currentProfile = data;
                this._session.loggedIn = true;
                this._router.navigate(['Home']);
            },
            err => {}
        );
    // <<== at this point above code hasn't been executed yet and no values are set
}

If you need code to be executed when the data arrives, you need to move it inside the callback.

If the caller of login needs access to the received data, it has to wait as well until the data arrives. You can achieve this by returning the observable

login() {
    return this._auth.login(this.email, this.password)
        .map(
            data => {
                this._session.currentProfile = data;
                this._session.loggedIn = true;
                this._router.navigate(['Home']);
            }
        );
}

You can't use subscribe in this case because it returns a Subscription. If you use map instead, then a Observable is returned which can be used by the caller like

this.login().subscribe(data => this.doSomething());

This way when doSomething() is called, _session.currentProfile, _session.loggedIn are set and router.navigate() has been called.

Async execution always needs to be properly chained and there is no way to go back to sync execution from an async call.

Sign up to request clarification or add additional context in comments.

4 Comments

ok clear. Maybe it is a different problem. When i log the value of this._session.loggedIn right after it is set it is right but then i navigate to a new component Homein which i inject the SessionService once again and there the value of this._session.loggedIn is incorrect. I thought in angular2 all services are singleton?
You don't seem to store the values in the service. Only in the component that called login(). Services in Angular2 are singletons per provider. If you provide it on a component, you get a service instance for every component instance. If you provide it in a lazy loaded module, you get another instance because providers of lazy loaded modules are not collected in root providers (they have they own root scope. Providers added to other @NgModules() are collected in the apps root scope and there will only be a single instance.
I think that´s the problem. So i just need to register the service with @NgModules() in app.module.ts and it should work?
Either that, or add it to providers: [AuthenticationService] of some other @NgModule() that you then add to imports: [] in app.module.ts.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.