简体   繁体   中英

Angular2 set variable on subscribe not working

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());
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM