dnc253
dnc253

Reputation: 40327

Use custom Http service in Ionic 2 app

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?

Upvotes: 0

Views: 748

Answers (3)

Gustavo Lopes Mourad
Gustavo Lopes Mourad

Reputation: 21

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]
    }

  ]

Upvotes: 1

sebaferreras
sebaferreras

Reputation: 44659

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.

Upvotes: 1

Tuong Le
Tuong Le

Reputation: 19220

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

Upvotes: 0

Related Questions