Использование одного экземпляра службы для всего приложения в angular2

Я делаю приложение Angular2. У меня есть класс службы входа в систему, который предоставляется на уровне приложения и используется компонентом входа и службой защиты аутентификации.

Если мое понимание DI правильное, как только служба предоставляется на уровне приложения через метаданные поставщиков AppModule, один и тот же экземпляр службы предоставляется всем компонентам при внедрении и, следовательно, изменение члена класса службы на один компонент будет отражен в другом сервисе или классе компонентов.

Я предоставил класс службы входа в систему на уровне приложения, но изменение переменной-члена службы из одного компонента не отражается в другом компоненте. Мой компонент входа в систему изменяет переменную loggedIn на true, но когда я обращаюсь к ней из службы защиты авторизации, она все равно получает ложное значение.

Ниже приведены мои фрагменты кода:

Модуль приложения

@NgModule({
imports: [
    BrowserModule,
    HttpModule,
    ReactiveFormsModule,
    MyModule
],
providers: [
    AuthguardService,
    LoginService
],
declarations: [
    AppComponent,
],
exports: [
],
bootstrap: [AppComponent],
})
export class AppModule { }

Служба аутентификации

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

import { LoginService } from './mymodule/login';

@Injectable()
export class AuthguardService implements CanActivate {

    constructor(
        private service: LoginService, 
        private router: Router
    ) { }
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean{
         let url: string = state.url;
         return this.checkLogin(url);
    }

    private checkLogin(url: string){
        debugger;
        if (this.service.isLoggedIn()) {
            console.log(this.service.loggedIn);
            return true;
        } else {
            console.log(this.service.loggedIn);
            this.router.navigate(['/']);
            return false;
        }
    }
}

Служба входа в систему

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

@Injectable()
export class LoginService {
    loggedIn: boolean = false;
    constructor(
        http: Http
    ){}

    login(username: string, password: string){
        let header = new Headers({
            'Content-Type': 'application/json',
            'Accept': 'application/json',
        });
        return this.http.post(
            'http://localhost/api/login',
             JSON.stringify({login:username,password:password}),
             {headers: headers}).map((res: Response)=>{
                 this.loggedIn = true;
                 return res.json();
             })
             .catch(this.handleError);
    }
    logout(){
        this.loggedIn = false;
    }
    isLoggedIn(){
        if(this.loggedIn == true){
            return true;
        } else {
            return false;
        }
    }
    private handleError(error: Response) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }
}

Может ли кто-нибудь сказать мне, что я делаю неправильно здесь. Когда я вызываю службу входа в систему из компонента входа в систему, вход выполняется успешно, и для переменной loggedIn устанавливается значение true, но когда я пытаюсь перенаправить ее на другой маршрут, а AuthguardService использует службу входа в систему, значение loggedIn равно false. Я проверил весь класс модуля, если есть несколько поставщиков службы входа в систему, но их нет.

Любая помощь приветствуется.


person kanra-san    schedule 05.12.2016    source источник
comment
Вы заново создаете службу, перенаправляя ее на другие маршруты? Попробуйте использовать шаблон проектирования singleton (en.wikipedia.org/wiki/Singleton_pattern), чтобы реализовать это. оказание услуг. Затем он создаст один объект и вернет его на все запросы. Я думаю, это сработает. :)   -  person Dilanka Rathnayake    schedule 05.12.2016
comment
Я прочитал много сообщений о службе singleton в angular2. Все они говорят, что angular2 использует ИЕРАРХИЧЕСКУЮ ЗАВИСИМОСТЬ ВНЕДРЕНИЯ, поэтому, если мне нужно использовать один и тот же экземпляр класса обслуживания, я должен предоставить его только на корневом уровне и удалить метаданные поставщиков из других модулей и компонентов, которые я сделал. Но я все еще не могу получить результат.   -  person kanra-san    schedule 05.12.2016
comment
пожалуйста, попробуйте переменную loggedIn как статическую (static loggedIn: boolean = false). Я думаю, это сработает :)   -  person Dilanka Rathnayake    schedule 05.12.2016
comment
я это тоже уже пробовал. К сожалению, это тоже не работает.   -  person kanra-san    schedule 05.12.2016
comment
о :( статические переменные принадлежат классам. Поэтому, если вы изменили их в одном месте, они должны измениться для всех мест. Я думаю, что проблема не в вашем классе обслуживания:/   -  person Dilanka Rathnayake    schedule 05.12.2016
comment
К вашему сведению, моя защита авторизации находится в папке корневого уровня, то есть src>app>auth-guard.service.ts, а моя служба входа находится в src>app>mymodule>login>login.service.ts. Я новичок в angular2, поэтому проблема может быть в файловой структуре или в чем-то еще.   -  person kanra-san    schedule 05.12.2016


Ответы (2)


Это может произойти, если вы добавите свою службу в массив поставщиков любого другого компонента, кроме module.ts.

person Raja Avinash    schedule 05.12.2016
comment
Проверено несколько раз, но я не предоставил его нигде, кроме app.module.ts - person kanra-san; 05.12.2016

Кажется, проблема заключалась в том, как я отправил форму. Я вызвал метод login() при нажатии кнопки, а не (ngSubmit), поэтому, когда я нажимаю кнопку входа в систему, сначала срабатывает событие click, а затем событие отправки. И событие отправки перезагружало все приложение, заставляя его создавать новый экземпляр всего. Всегда используйте событие (ngSubmit) для отправки формы.

person kanra-san    schedule 13.12.2016