Jeremy Thomas
Jeremy Thomas

Reputation: 6684

When do Angular 2 services initialize

I have a shared service that I am using to store global variables like authentication tokens. I am having issues ensuring that the value is getting updated and that the newest value is being used in my components. For example:

import {Injectable} from '@angular/core';

@Injectable()
export class GlobalVariablesProvider {

  private auth_token: string;

  constructor() {}

  getAuthToken() {
    return this.auth_token
  }

  setAuthToken(auth_token) {
    this.auth_token = auth_token
  }
}

and then in my login-component I set the auth_token:

this.clientService.login(user).subscribe(
  successData => {
    this.current_user = successData["user"]
    this.globalService.setAuthToken(this.current_user.auth_token)
  }
}

but when I navigate to a different page / use a new component, occasionally the auth_token is out of sync (I believe if the service is being re-initialized and losing the auth_token value).

this.auth_token = this.globalVarService.getAuthToken()
// occasionally returns null

Is there a way to ensure that nce this variable is set, the value remains even after being injected into another component?

Upvotes: 2

Views: 4299

Answers (2)

vanelizarov
vanelizarov

Reputation: 1073

First, import service in the root module of your app and insert it into providers section in NgModule declaration. From now it will act like a singleton and will be available for all components in your app without passing it into each component's providers.

If you want to always keep auth_token in sync with each component you inject this service to, you might use Subjects from rxjs package, which is included in Angular installation. There is a good post on Medium about it. For example:

import {Injectable} from '@angular/core';
import { Subject } from 'rxjs/Subject'

@Injectable()
export class GlobalVariablesProvider {

  private auth_token: Subject<string> = new Subject<string>()

  constructor() {}

  getAuthToken() {
    return this.auth_token
  }

  setAuthToken(auth_token) {
    this.auth_token.next(auth_token)
  }
}

Then, inject it in components you need. Then, if you need to get current token, instead of using value received from getAuthToken(), you can subscribe to it. So, your component will be always in sync with current token:

this.globalVarService
  .getAuthToken()
  .subscribe(token => {
    this.auth_token = token
  })

Upvotes: 2

tchelidze
tchelidze

Reputation: 8318

Declare service in root module to make it Singleton, since angular has hierarchical injector.

Upvotes: 2

Related Questions