Дубликаты корневой службы Angular

#angular #typescript

#angular #typescript

Вопрос:

У меня есть служба аутентификации, которая выглядит так: globalauth.service.ts

 import {Inject, Injectable} from '@angular/core';
import {GoogleLoginProvider, SocialAuthService, SocialUser} from 'angularx-social-login';
import {Router, RouterModule} from '@angular/router';
import {Observable} from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class GlobalAuthService{
  public userData: SocialUser;
  public get isLogged(): boolean{
    return this.userData != null;
  }
  constructor(private socialAuthService: SocialAuthService, private routerModule: RouterModule, private router: Router) {
    console.log('constructor');
    this.socialAuthService.authState.subscribe((user) => {
      this.userData = user;
      console.log(user);
    });
  }
  public GoogleSignIn(): void{
    console.log('starting auth...');
    this.socialAuthService.signIn(GoogleLoginProvider.PROVIDER_ID);
    console.log('authed!');
  }
  public SignOut(): any{
    this.socialAuthService.signOut();
  }
}
  

Проблема в том, что он создается более одного раза в течение срока службы приложения.
Каждый раз, когда я выполняю маршрутизацию к компоненту, который его использует, создается экземпляр службы. Я знаю это, потому что он записывает «конструктор» в консоль при вызове конструктора.
Итак, он вызывается в 2 местах, одно из них — authentication.component.ts:

 import {Component, OnInit} from '@angular/core';
import {GlobalAuthService} from './globalauth.service';

@Component({
  selector: `app-authentication`,
  templateUrl: `./authentication.component.html`,
  styleUrls: ['./authentication.component.css']
})
export class AuthenticationComponent{
  constructor(public authenticationService: GlobalAuthService) {
  }
  public authenticate(): void{
    this.authenticationService.GoogleSignIn();
  }
  public signOut(): void{
    this.authenticationService.SignOut();
  }
}
  

И второй: app.component.ts

 import {Component, OnInit} from '@angular/core';
import {SocialAuthService} from 'angularx-social-login';
import {GoogleLoginProvider} from 'angularx-social-login';
import {SocialUser} from 'angularx-social-login';
import {Router} from '@angular/router';
import {GlobalAuthService} from './authentication/globalauth.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public title = 'test';
  constructor(private routerService: Router, public authService: GlobalAuthService) {

  }

}
  

My app.module.ts

 import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import {SocialLoginModule, SocialAuthServiceConfig, SocialAuthService} from 'angularx-social-login';
import {GoogleLoginProvider} from 'angularx-social-login';

import {MailsComponent} from './mailmanager/mails.component';
import {RouterModule, Routes, RoutesRecognized} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {AuthenticationComponent} from './authentication/authentication.component';
import {APP_BASE_HREF, CommonModule} from '@angular/common';
import {HttpClient, HttpClientModule} from '@angular/common/http';

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'addmails', component: MailsComponent},
  {path: 'login', component: AuthenticationComponent}
];

@NgModule({
  declarations: [
    AppComponent,
    MailsComponent,
    HomeComponent,
    AuthenticationComponent,
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot(appRoutes),
    CommonModule,
    SocialLoginModule,
    HttpClientModule
  ],
  providers: [
    HttpClient,
    {
      provide: 'SocialAuthServiceConfig',
      useValue: {
        autoLogin: false,
        providers: [
          {
            id: GoogleLoginProvider.PROVIDER_ID,
            provider: new GoogleLoginProvider(
              'some hyper super duper secret key'
            ),
          },
        ],
      } as SocialAuthServiceConfig,
    },
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
  

Мой app.component.html

 <div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
  <a class="navbar-brand mr-auto  my-0 mr-md-auto font-weight-normal" style="color: black" href="/">Mail Manager</a>
  <nav class="my-2 my-md-0 mr-md-3">
    <a class="p-2 text-dark" href="/addmails">Добавить</a>
  </nav>
  <a *ngIf="!authService.isLogged" class="btn btn-secondary" style="color: white" href="/login">Вход</a>
  <p *ngIf="authService.isLogged">Добро пожаловать, {{authService.userData.name}} !</p>
  <a class="btn btn-outline-primary" href="#">Регистрация</a>
</div>
<main role="main" class="container">
  <router-outlet></router-outlet>
</main>
  

Пожалуйста, помогите мне! Я застрял на нем около 2 дней и не могу понять, что я делаю неправильно.

Комментарии:

1. можете ли вы создать stackblitz?

2. Да, конечно! angular-ivy-ymvyag.stackblitz.io Вы должны обратить свое внимание на консоль при переходе между страницей входа в систему и главной страницей

Ответ №1:

Согласно вашему примеру прикрепленной ссылки: после нажатия на кнопку входа ваша страница обновляется, поэтому ваш сервис (GlobalAuthService) будет создан снова.

не используйте href , пользователь routerLink . измените свой тег с :

   <a *ngIf="!authService.isLogged" class="btn btn-secondary" style="color: white" href="/login">Login</a>
  

Для

   <a *ngIf="!authService.isLogged" class="btn btn-secondary" style="color: white" routerLink="/login">Login</a>
  

Stackblitz здесь

Комментарии:

1. Хорошо, спасибо, это помогло! Но он сбрасывается после обновления страницы. Нормально ли, что одноэлементная служба сбрасывается после обновления страницы?

2. @Fedir Katushonok — Да