Home > OS >  Angular 7 - correctly initialize variable in constructor
Angular 7 - correctly initialize variable in constructor

Time:02-02

New to Angular and wondering how to correctly initialize variables in an service.ts file. The purpose being to dry up my code a bit.

export class CollectionsService {
  private urlBase: string;
  private token: string;
  constructor(
    private authorized: AuthService,
    private http: Http,
    private httpHelper: HttpHelperService
  ) {
    this.urlBase = `/app/${this.authorized.user.appdomainid}`; 
    this.token = this.authorized.user.token;
    // this.authorized = undefined
  }
  // ...
}

If I just put the url base directly in a method it's fine:

getCollections(): Observable<any> {
    return this.http
      .get(
        `/app/${this.authorized.ampUser.appdomainid}/collections`,
        this.httpHelper.getRequestOptions(this.authorized.ampUser.token)
      )
      .pipe(map((response) => <any>response.json()))
      .pipe(map((response) => response.Items))
      .pipe(
        catchError((err) => {
          return throwError(err.json());
        })
      );
  }

CodePudding user response:

There's nothing wrong with keeping the base URL and token as instance variables on your service. Redefining them in each method seems inefficient and repetitive, but it makes sense if you want to react to changes in the AuthService.

If that is the concern, you might consider using property getters instead:

@Injectable({
  providedIn: 'root'
})
export class CollectionsService {

  private get urlBase(): string {
    return `/app/${this.authorized.ampUser.appdomainid}`;
  }

  private get token(): string {
    return this.httpHelper.getRequestOptions(this.authorized.ampUser.token);
  }

  constructor(
    private http: HttpClient,
    private authorized: AuthService,
    private httpHelper: HttpHelperService
  ) {}

  getCollections(): Observable<any> {
    return this.http
      .get(
        `${this.urlBase}/collections`,
        this.token
      )
      .pipe(map((response) => <any>response.json()))
      .pipe(map((response) => response.Items))
      .pipe(
        catchError((err) => {
          return throwError(err.json());
        })
      );
  }
}

If you're really looking to DRY, you could make it an InjectionToken that's provided to your whole application. Any number of services could rely on these tokens without needing to instantiate/maintain their own instance variables.

You can make sure you react to changes in AuthService by providing the tokens with the useFactory strategy.

In your app.module.ts:

import { AuthService } from 'auth.service.ts';
import { HttpHelperService } from 'http-helper.service.ts';

const BASE_URL = new InjectionToken<string>('BaseUrl');
const API_TOKEN = new InjectionToken<string>('ApiToken');

@NgModule({
  providers: [
    { 
      provide: BASE_URL, 
      useFactory: (authorized: AuthService) => `/app/${authorized.ampUser.appdomainid}`,
      deps: [AuthService] 
    },
    { 
      provide: API_TOKEN,
      useFactory: (authorized: AuthService) => authorized.ampUser.token,
      deps: [AuthService]
    }
  ],
})
export class AppModule {}

Then in your collections.service.ts:

import { BASE_URL, API_TOKEN } from 'app.module.ts';

@Injectable({
  providedIn: 'root'
})
export class CollectionsService {

  constructor(
    private http: HttpClient,
    private httpHelper: HttpHelperService,
    @Inject(BASE_URL) private baseUrl: string,
    @Inject(API_TOKEN) private apiToken: string
  ) {}

  getCollections(): Observable<any> {
    return this.http
      .get(
        `${this.baseUrl}/collections`,
        this.httpHelper.getRequestOptions(this.apiToken)
      )
      .pipe(map((response) => <any>response.json()))
      .pipe(map((response) => response.Items))
      .pipe(
        catchError((err) => {
          return throwError(err.json());
        })
      );
  }

  deleteCollection(listId: unknown): Observable<any> {
    const body = { foo: 1, bar: 2 };
    return this.http
      .delete(
        `${this.baseUrl}/collections/${listId}/rows`,
        this.httpHelper.getRequestOptionsWBody(this.apiToken, body)
      )
      .pipe(map((response) => <any>response.json()))
      .pipe(map((response) => response))
      .pipe(
        catchError((err) => {
          return throwError(err.json());
        })
      );
  }
}
  • Related