Search code examples
webpackangular-http-interceptorstypescript2.0angularjs-1.5

AngularJS 1.x TypeScript (with Webpack) Interceptor issue


I've just started on TypeScript, so I think it is something very silly. I've gone through couple of dozens links but can't find exactly what is the issue that my service instance is undefined. So my app structure is simple(?): Using AngularJS 1.5 with TypeScript and Webpack. My Main app file is as below:

     // External 
    import ng = require("angular");

     // App modules
    import authIntSvc = require("./security/authInterceptorSvc");

     // Note: Can't use require as it returns object and we need function
    import localStorageHandler from "./core/localStorageCfg";
    import routingHandler from "./uiRoutes";


    export
    let ptaToolsApp = ng.module('ptaToolsApp', [
      'ngRoute', 'ngStorage',
      'ptaTools.CoreMod'
    ]);

    ptaToolsApp
      .config(routingHandler)
      .config(localStorageHandler);

    console.info("All Done...! " + new Date());

     // Add services
    import secSvc = require("./security/SecuritySvc");
    ptaToolsApp.service(secSvc.SecuritySvc.IID, secSvc.SecuritySvc);

     //import { interceptorInitiator } from "./security/authInterceptorSvc";
    ptaToolsApp.service(authIntSvc.authInterceptorSvc.IID, authIntSvc.authInterceptorSvc);

    ptaToolsApp.config(authIntSvc.interceptorInitiator);

     // Add module controlles - TODO: FInd better way 
    import {
      HomeCtrl
    }
    from "./userHome/homeCtrl";
    ptaToolsApp.controller(HomeCtrl.IID, HomeCtrl);

     // App Init --------- Run function ---------------------------------------
    function runApp(authSvc: secSvc.SecuritySvc) {
      authSvc.checkAuthData();
    }

    runApp.$inject = [secSvc.SecuritySvc.IID];

     // Run App
    ptaToolsApp.run(runApp);

     // App Init --------- Run function ---------------------------------------

     // Dummy requires, just needed for WebPack to pack it in bundle
    import coreMod = require("./core/coreModule");
    const a1 = coreMod;
    import ngRoute = require("angular-route");
    const a2 = ngRoute;
    import ngStorage = require("ngstorage");
    const a3 = ngStorage;

My Interceptor file is as below:

    import ng = require("angular");

    import {
      appLocalStorageSvc
    }
    from "../core/appLocalStorageSvc";
    import * as secModels from "./models";

     //  implements ng.IHttpInterceptor
    export class authInterceptorSvc {

      public static readonly IID = "sec.authInterceptorSvc";

      static $inject = ['$location', '$q', appLocalStorageSvc.IID];

      constructor(private $location: ng.ILocationService, private $q: ng.IQService, private appLocalStorage: appLocalStorageSvc) {
        console.info('constructor:: ' + authInterceptorSvc.IID);
      }

      //public request(reqCfg: ng.IRequestConfig): ng.IRequestConfig {
      public request(reqCfg: any): any {
        reqCfg.headers = reqCfg.headers || {};
        // if ((this.appLocalStorage.authData) && (this.appLocalStorage.authData.isAuth === true))
        //     reqCfg.headers.Authorization = 'Bearer ' + this.appLocalStorage.authData.oAuthToken;

        console.info("in authInterceptorSvc.request");
        console.debug(reqCfg);
        console.debug(JSON.stringify(this));

        return reqCfg;
      }

      // HTTP Rejection
      public responseError(rejection: any) {
        if (rejection.status === 401) {
          this.$location.path('/login');
          return this.$q.reject(rejection);
        }
        return this.$q.reject(rejection);
      }
    }

    export
    function interceptorInitiator($httpProvider: ng.IHttpProvider) {
      $httpProvider.interceptors.push(authInterceptorSvc.IID);
    }

    interceptorInitiator.$inject = ["$httpProvider"];

So, in above method request(reqCfg: any): any I've commented lines where I need to access local variable for appLocalStorage, I get error that "can't access property 'appLocalStorage' of undefined".

** I added console.log in all my service constructors (will remove later). When I page load my app loads fine till interceptor is hit. In the request function my service instance is undefined. See the log below:

Console Log

I've highlighted the "undefined" as a result of console.debug(JSON.stringify(this));

I'm wondering why my this in service is undefined.

Another not a big issue, I think, just practice, if you see those dummy lines in the end of main app file. Why do I need to tell webpack something that basic?

Can someone pls help?

As my answer below the main issue is solved
But the minor issue of putting dummy lines so that webpack bundles my files still stays.


Solution

  • After doing more digging, I found the answer here: (The question was almost same as mine) TypeScript interceptor in AngularJS

    So the issue was how interceptor works differently than controller or services.
    You need to make it objectify (as explained in the answer in above post).

    public request = (config) => {
      // this.TokenService is undefined here as well as $window or $q which I tried to inject
      config.headers = config.headers || {};
      if (this.TokenService.Token != "")
        config.headers.Authorization = 'Bearer ' + this.TokenService.Token;
      return config;
    }

    As shown above works fine.