Reputation: 10386
I am trying to use the Angular 2 Router Lazy Loading to reduce initial load time.
In my app I have customized the original Http service of the Angular to display a loader whenever any http request is initiated which I hide on completion.
Currently, I have a GlobalService (which is a application wide singleton) which hold the current status of the Loading bar and HttpLoading class which extends Angular original Http class.
In AppModule I have added both to the providers so that these are available application wide:
export function httpFactory(backend: XHRBackend, defaultOptions: RequestOptions, globalService: GlobalService) {
return new HttpLoading(backend, defaultOptions, globalService);
}
and
providers: [
GlobalService,
{
provide: Http,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, GlobalService]
}
],
I have the below AppModule:
//angular
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Http, XHRBackend, HttpModule, RequestOptions, JsonpModule } from '@angular/http';
import { NgModule } from '@angular/core';
//material
import { MdProgressBarModule } from '@angular2-material/progress-bar';
import { HomeModule } from './home/home.module';
import { AppComponent } from './app.component';
//services
import { GlobalService } from './shared/services/global.service';
import { HttpLoading } from './shared/services/http-loading';
//routing
import { routing } from './app.routing';
export function httpFactory(backend: XHRBackend, defaultOptions: RequestOptions, globalService: GlobalService) {
return new HttpLoading(backend, defaultOptions, globalService);
}
@NgModule({
imports: [
//angular
BrowserModule,
FormsModule,
HttpModule,
JsonpModule,
ReactiveFormsModule,
routing,
//material
MdProgressBarModule.forRoot(),
HomeModule,
],
declarations: [
AppComponent,
],
providers: [
GlobalService,
{
provide: Http,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, GlobalService]
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
Below is my HttpLoading Class:
import { Http, ConnectionBackend, RequestOptions, RequestOptionsArgs, Response, Headers } from '@angular/http';
import { Injectable } from '@angular/core';
import { GlobalService } from './global.service';
import { Observable } from 'rxjs/Observable';
import "rxjs/add/operator/catch";
export class HttpLoading extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _gs: GlobalService) {
super(backend, defaultOptions);
}
get(url: string, options?: RequestOptionsArgs): Observable<any> {
this._gs.isLoading = true;
return super.get(url, options)
.map(res => {
this._gs.isLoading = false;
return res.json();
});
}
}
Below is my GlobalService
import { Injectable, Inject } from '@angular/core';
@Injectable() export class GlobalService { public isLoading: boolean = false; }
I tried to create below SharedModule which I thought I would inject in the AppModule and it will solve the problem:
import { NgModule, ModuleWithProviders } from "@angular/core";
import { Http, XHRBackend, HttpModule, RequestOptions, JsonpModule } from '@angular/http';
import { GlobalService } from './shared/services/global.service';
import { HttpLoading } from './shared/services/http-loading';
export function httpFactory(backend: XHRBackend, defaultOptions: RequestOptions, globalService: GlobalService) {
return new HttpLoading(backend, defaultOptions, globalService);
}
@NgModule({
imports: [
//angular
HttpModule,
JsonpModule
]
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [GlobalService,
{
provide: Http,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, GlobalService]
}]
};
}
}
And updated my AppModule to the below:
//angular
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Http, XHRBackend, HttpModule, RequestOptions, JsonpModule } from '@angular/http';
import { NgModule } from '@angular/core';
//material
import { MdProgressBarModule } from '@angular2-material/progress-bar';
import { HomeModule } from './home/home.module';
import { SharedModule } from './../shared.module';
import { AppComponent } from './app.component';
//routing
import { routing } from './app.routing';
@NgModule({
imports: [
//angular
BrowserModule,
FormsModule,
HttpModule,
JsonpModule,
ReactiveFormsModule,
routing,
//material
MdProgressBarModule.forRoot(),
HomeModule,
SharedModule
],
declarations: [
AppComponent,
],
bootstrap: [AppComponent]
})
export class AppModule { }
But it didn't work. Whenever I visit any route which has http call, it throws error on console.
For example, in HomeCompnent in ngOnInit I make an http call to fetch some data. But when I move to this component, I displays below error in console.
EXCEPTION: _super.prototype.get.call(...).map is not a function
core.umd.js:3468 TypeError: _super.prototype.get.call(...).map is not a function
at HttpLoading.get (http-loading.js:50)
at HomeComponent.ngOnInit
Can anyone please guide what am I doing wrong?
Upvotes: 0
Views: 504
Reputation: 5092
In HttpLoading class file, add
import 'rxjs/add/operator/map';
You don't need method 1 if you do this.
In main.ts
import 'rxjs';
In systemjs.config.js;
map: {
'rxjs': 'node_modules/rxjs',
},
packages: {
'rxjs': { main: 'bundles/Rx.min.js', defaultExtension: 'js' },
Upvotes: 1