1

I am creating a service to generate a random token and pass it to a request (In developers Spotify they strongly recommend you to do so). There is a query parameter (state)!

This is my Service:

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

@Injectable()
export class TokenService {
    private _state: string;

    constructor() {
        alert('Token got created');
    }

    public get state(): string {
        return this._state;
    }

    generateToken() {
        this._state = this.randomString() + this.randomString();
        alert(this._state);
    }

    private randomString() {
        return Math.random().toString(36).substring(2);
    }
}

And I am calling it here:

...
@Injectable()
export class AngularSpotifyService { 
...
constructor(private windowRef: WindowService, private token: TokenService) { }

getToken(windowName = this.name, windowOptions = this.getOptions()) {
    this.windowRef.nativeWindow.open(`https://accounts.spotify.com/authorize?${this.toQueryString()}`,
      windowName, windowOptions);
}

private toQueryString(): string {
    this.token.generateToken();
    return `client_id=${this.clientId}&response_type=${this.responseType}&redirect_uri=${this.redirectUri}&state=${this.token.state}`;
}

The two services are getting created twice, when launch the app and when the response from spotify arrived.

Expected behaviour: I am generating a random string to fill the state query parameter. When the response arrived I am expecting that the token service not to get created again(I supposed is the normal behaviour) because if so, it is going to generate a new random string and then, the state query parameter (that is returned again with the Spotify response) are not longer equal.

This is my app.module:

...
@NgModule({
  declarations: [
      AppComponent,
      TokenComponent,
      AngularSpotifyComponent
  ],
  imports: [
      BrowserModule,
      RouterModule.forRoot(appRoutes)
  ],
  providers: [WindowService, AngularSpotifyService, TokenService],
  exports: [ RouterModule ],
  bootstrap: [AppComponent]
})
export class SpotifyModule { }
Zze
  • 18,229
  • 13
  • 85
  • 118
Luillyfe
  • 6,183
  • 8
  • 36
  • 46

1 Answers1

1

You can do this via static properties ("object initializers") in your class / service. I made this plunkr to demonstrate.

But the crux of it is that the variable declaration is done outside of the constructor and is computed during the "spin up" time of the class thus instantiating it multiple times does not impact the value.

export class Example{
  static value: string = Math.random().toString(36).substring(2);

  constructor(){
    console.log(Example.value);
  }

  public getValue(){
    return Example.value;
  }
}

this.example1 = new Example();
this.example2 = new Example();


// NOW!
this.example1.getValue() == this.example2.getValue()

So just to clarify the point I am making...

Replace private _state: string; with the class above, and then use example.getValue() wherever you were using _state previously.

So the new service will look like:

@Injectable()
export class TokenService {
    private example: Example;

    constructor() {
        this.example = new Example();
        alert('Token got created');
    }

    public get state(): string {
        return this.example.getValue();
    }

}

Obviously you would probably rename the Example class to whatever you find appropriate.

Zze
  • 18,229
  • 13
  • 85
  • 118
  • Just one problem with this answer, you are creating two instances of Example which is class (and you are using the new keyword), in my case I am using a Service to generate the token. The problem here is that the Services on Angular are singleton (they share the same instance across the whole app). But as I stated in the question I am facing some quirky behavior. – Luillyfe Feb 06 '18 at 17:36
  • Sorry your solution does not work at all. When the response for Spotify arrived, the Service get re-executed or re- created, so this line: **static value: string = Math.random().toString(36).substring(2)**, got computed a second time, with that in mind the two values are not longer equals ! – Luillyfe Feb 06 '18 at 18:04
  • @Luillyfe I have also just updated the plunkr with a working example. – Zze Feb 06 '18 at 21:10