0

I have some things I want to do with every HTTP request in my Ionic 2 app (v2.0.0-beta.30), so I have created my own Http class that extends angular's service. Something like this:

@Injectable()
export class myHttp extends Http
{
    private myStuff(): void
    {
        //stuff to fo every request
    }

    public request(url: string | Request, options?: RequestOptionsArgs): Observable<Response>
    {
        this.myStuff();
        return super.request(url, options);
    }

    public get(url: string, options?: RequestOptionsArgs): Observable<Response>
    {
        this.myStuff();
        return super.get(url, options);
    }
// etc.
}

I have stuff currently calling function on Http, and I don't want to have to change every thing to call MyHttp. I want anything making requests to not know and not care that it is actually calling MyHttp. It seems like there should be a way to provide MyHttp instead of Http, I'm just not sure where you would do this with an Ionic 2 app.

I tried adding it the ionicBootstrap function like this:

ionicBootstrap(MyApp, [new ProviderBuilder(Http).toClass(MyHttp)], {});

This just gives me the white screen of death. I also tried adding to the @Component decorator of MyApp class like this:

@Component({
    providers: [new ProviderBuilder(Http).toClass(MyHttp)],
    templateUrl: "build/app.html"
})

This gives the same white screen. I'm not sure I understand the difference, by I tried toAlias instead of toClass with the same result.

How do I tell the injector to inject MyHttp when anything wants to inject Http?

-------- UPDATE -----------

I finally got around the white screen of death with my attempts by also including HTTP_PROVIDERS in the array of providers. However, it's still injecting Http instead of MyHttp in the other services using it. I've tried each of the following:

{ provide: Http, useClass: MyHttp }
provide(Http, {useClass: myHttp })
new ProviderBuilder(Http).toClass(MyHttp)

The service that is dependent on Http looks like this:

public constructor(http: Http)
{
    //...
}

I put a debugger in here and I can see it is angular's Http instead of MyHttp.

-------- UPDATE 2 -----------

I tried to the same thing with a different class, and I do see it working. For example:

ionicBootstrap(MyApp, [new ProviderBuilder(MyOtherClass).toClass(MyOtherClass2)], {});

I see MyOtherClass2 getting injected when it asks for MyOtherClass. So, I don't know if I'm doing something wrong in MyHttp or if maybe there's some bug with Http. Has anyone been able to successfully do this with Http?

dnc253
  • 39,967
  • 41
  • 141
  • 157

3 Answers3

1

Just like you can read here, when you register a provider like this:

// bootstrap
ionicBootstrap(MyApp, [DataService]);

// component
@Component({
  ...
  providers: [DataService]
})
class AppComponent { }

You're using a shortcut, instead of writting this:

// at bootstrap
ionicBootstrap(MyApp, [
  provide(DataService, {useClass: DataService})
]);

// or in component
@Component({
  ...
  providers: [
    provide(DataService, {useClass: DataService})
  ]
})
class AppComponent { }

You can use that shortcut because the value of it is the same as the token. So in your case, you'd have to do it like this:

// at bootstrap
ionicBootstrap(MyApp, [
  provide(Http, { useClass: myHttp })
]);

// or in component
@Component({
  ...
  providers: [
    provide(Http, {useClass: myHttp })
  ]
})
class AppComponent { }

Remember that if you add it in the Component a new instance of that service will be created everytime that component gets loaded. If you want to use the same instance in the entire application (singleton) you'd have to add it in the ionicBootstrap or in the top-most Component from your app.

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
  • I first tried the `provide` function like you have here, but then saw in the angular source that it is deprecated. That's why I tried using `ProviderBuilder`. I tried what you have above, and I get the white screen. I don't know if I'm just missing something else in my app or what... – dnc253 Jul 14 '16 at 14:52
  • Please see my updated question to see if there is any more information you can provide. Thanks. – dnc253 Jul 14 '16 at 15:24
  • Have you tried by creating an alias for the Http service? Just like you can read [here](https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#injector-providers) you can do this by adding `[MyHttp, { provide: Http, useExisting: MyHttp }]`. That way, the same instance of your custom service will be used both for resolving the Http and the MyHttp reference. – sebaferreras Jul 16 '16 at 14:42
  • I have tried this without success. I just added another update to my question. Things seem to work when not dealing with `Http`. I'm not sure what I would be doing wrong with `MyHttp`. – dnc253 Jul 18 '16 at 15:23
1

This worked for me:

Your myHttp should start with the constructor:

@Injectable()
export class myHttp extends Http{
...
    constructor(
        xhrBackend: XHRBackend,
        requestOptions: RequestOptions) {
        super(xhrBackend, requestOptions);
    }

And in your app.module.ts you should import your provider as:

import { Http, XHRBackend, RequestOptions } from '@angular/http';
...

@NgModule({
  ...
  providers: [
    {
      provide: Http,
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
        return new myHttp(backend, defaultOptions);
      },
      deps: [XHRBackend, RequestOptions]
    }

  ]
0

You can't use [new...], can you try { provide: Http, useClass: MyHttp } It will be ionicBootstrap(MyApp, [{ provide: Http, useClass: MyHttp }], {});

Tuong Le
  • 18,533
  • 11
  • 50
  • 44
  • I tried this, and I get the white screen in my app. Like my comment in the other answer, I'm not sure if I'm just missing something else in my app. – dnc253 Jul 14 '16 at 14:53
  • Please see my updated question to see if there is any more information you can provide. Thanks. – dnc253 Jul 14 '16 at 15:24