【问题标题】:How long does an Angular2 service hold the class variable valuesAngular2 服务将类变量值保存多长时间
【发布时间】:2017-03-19 09:08:22
【问题描述】:

我有一个带有数据服务的 Angular2 应用程序,它应该根据当前登录的用户显示不同的内容。 我的问题是我的身份验证服务在首次构建数据值后没有存储数据值,这使我无法访问其他数据提供者中的用户 ID。

这是我目前通过 2 个服务、1 个组件和 1 个 authguard 完成的工作(见下文)。我期望的逻辑是:

  1. Authguard 在收件箱路由激活之前调用
  2. Authguard 调用订阅 FirebaseAuth 的 AuthService 并设置 authState 变量
  3. 如果用户始终登录,DataService 应该具有来自 AuthService 的 authService.id 值

但是,发生的情况是 authService.id 产生 'Not set',因为即使用户已登录,它似乎也从未设置过。这可以通过在后面添加 console.log(state) 来证明在当前打印当前登录用户的 AuthService 中订阅 auth$。

因此,我的问题是变量 private authState 存储在 AuthService 中多久?在我的 DataService 中进行其他调用之前,是否有任何其他解决方案可以获取 authService.id 变量的可观察值?我能想到的一种解决方案是在 DataService 中为每个数据调用使用 switchmap,但这似乎不是最理想的。

AuthService

@Injectable()
export class AuthService {

  private authState: FirebaseAuthState = null;

  constructor(private af: AngularFire, public auth$: FirebaseAuth) {
    auth$.subscribe((state: FirebaseAuthState) => {
      this.authState = state;
    });
  }

  get authenticated() {
    return this.authState !== null;
  }

  get id(): string {
    return this.authenticated ? this.authState.uid : 'Not set';
  }
}

AuthGuard

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) {}

  canActivate(): Observable<boolean> {
    return this.authService.auth$
      .take(1)
      .map(authState => !!authState)
      .do(authenticated => {
        if (!authenticated) {
          this.router.navigate(['/compose']);
        }
      });
  }

}

数据服务

@Injectable()
export class EmailService {

  private emails: FirebaseListObservable<IEmail[]>;
  private emailUserPath: string;

  constructor(private af: AngularFire, authService: AuthService) {
    this.emailUserPath = `/emails/${authService.id}`;
  }

  getAllEmails(): FirebaseListObservable<IEmail[]> {
    return this.af.database.list(this.emailUserPath);
  }
}

路由模块

const routes: Routes = [
  { path: 'inbox',  component: InboxComponent, canActivate: [AuthGuard] }
];

@NgModule({
  imports: [ RouterModule.forChild(routes) ],
  providers: [AuthGuard],
  exports: [ RouterModule ]
})

export class EmailRoutingModule {}

应用模块

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { EmailsModule } from './emails/emails.module';

import { AppRoutingModule }     from './app-routing.module';
import { AngularFireModule, AuthProviders, AuthMethods } from 'angularfire2';
import { UserSearchComponent } from './shared/user-search/user-search.component';
import {AuthService} from "./auth/auth.service";
import {AuthGuard} from "./auth/auth-guard";
import {EmailRoutingModule} from "./emails/email-routing.module";
import { UserOrLoginComponent } from './navigation/user-or-login/user-or-login.component';
import { NavigationListComponent } from './navigation/navigation-list/navigation-list.component';

export const firebaseConfig = {
  apiKey: "hidden",
  authDomain: "hidden",
  databaseURL: "hidden",
  storageBucket: "hidden"
};

const myFirebaseAuthConfig = {
  provider: AuthProviders.Google,
  method: AuthMethods.Popup
};

@NgModule({
  declarations: [
    AppComponent,
    UserSearchComponent,
    UserOrLoginComponent,
    NavigationListComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    AppRoutingModule,
    EmailRoutingModule,
    AngularFireModule.initializeApp(firebaseConfig, myFirebaseAuthConfig),
    EmailsModule // I include the Emails module below here
  ],
  providers: [
    AuthService,
    AuthGuard
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

电子邮件应用模块

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ComposeComponent } from './compose/compose.component';
import { EmailDetailComponent } from './email-detail/email-detail.component';
import { InboxComponent } from './inbox/inbox.component';
import { ReplyComponent } from './reply/reply.component';
import { ReplyListComponent } from './reply/reply-list/reply-list.component';
import { EmailService } from './shared/email.service';

import { FormsModule } from '@angular/forms';
import {ReplyService} from "./reply/reply.service";

@NgModule({
  imports: [
    CommonModule,
    FormsModule
  ],
  declarations: [
    ComposeComponent,
    EmailDetailComponent,
    InboxComponent,
    ReplyComponent,
    ReplyListComponent
  ],
  providers: [
    EmailService,
    ReplyService
  ]
})

export class EmailsModule { }

export { EmailService };

【问题讨论】:

  • 您是否在AppModule 中提供AuthService 以使其成为全局单例?
  • 我在一个单独的 auth 模块中提供它,然后我将它导入到应用程序模块中

标签: angular firebase firebase-authentication observable


【解决方案1】:

只要他们活着,他们就会存储他们的价值观。当您导航到设置服务价值的模块之外的某个地方时,您将失去价值。因为您不再有权访问已设置值的实例。

每个提供商的服务都是单例的。这意味着如果您需要全局的服务/值,则需要在全局级别将其设为单例。在AppModule 提供AuthService 应该可以解决您的问题。

import { AuthService } from 'path/to/service'

@NgModule({
  imports: [ ],
  providers: [AuthService], //<-- provided globally
  exports: [ ]
})

export class AppModule {}

【讨论】:

  • 谢谢。但是,我已经在 NgModule 中将 AuthService 设置为提供程序:` @NgModule({ 声明:[ AppComponent, UserSearchComponent, UserOrLoginComponent, NavigationListComponent ], imports: [ BrowserModule, FormsModule, HttpModule, AppRoutingModule, EmailRoutingModule, AngularFireModule.initializeApp(firebaseConfig, myFirebaseAuthConfig), EmailsModule ], 提供者: [AuthService, AuthGuard], 引导程序: [AppComponent] }) 导出类 AppModule { }`
  • 请编辑您的问题并添加模块代码。这在 cmets 中不可读。您是否也在其他任何地方提供服务?
  • 好点 Stefa。我编辑了答案,并在上面包含了 App 模块和 Email 模块。如果你能找到任何看起来不合适的东西,请告诉我
猜你喜欢
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2012-08-24
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多