Angular 2 延迟加载和应用程序范围的单例 - 自定义 Http Class 不工作
Angular 2 Lazy Loading and Application-wide singletons - Custom Http Class Not working
我正在尝试使用 Angular 2 路由器延迟加载来减少初始加载时间。
在我的应用程序中,我自定义了 Angular 的原始 Http 服务,以便在启动任何 http 请求时显示一个加载器,我在完成时隐藏它。
目前,我有一个 GlobalService(这是一个应用程序范围的单例),它保存加载栏的当前状态和扩展 Angular 原始 Http class 的 HttpLoading class。
在 AppModule 中,我将两者都添加到提供程序中,以便它们在应用程序范围内可用:
export function httpFactory(backend: XHRBackend, defaultOptions: RequestOptions, globalService: GlobalService) {
return new HttpLoading(backend, defaultOptions, globalService);
}
和
providers: [
GlobalService,
{
provide: Http,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, GlobalService]
}
],
我有以下 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 { }
下面是我的 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();
});
}
}
下面是我的 GlobalService
从'@angular/core'导入{可注入,注入};
@Injectable()
导出 class 全球服务 {
public isLoading: boolean = false;
}
我尝试在下面创建 SharedModule,我认为我会在 AppModule 中注入它,它会解决问题:
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]
}]
};
}
}
并将我的 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 { 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 { }
但是没有用。每当我访问任何具有 http 调用的路由时,它都会在控制台上抛出错误。
例如,在 ngOnInit 的 HomeCompnent 中,我进行了一个 http 调用来获取一些数据。但是当我移动到这个组件时,我在控制台中显示以下错误。
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
任何人都可以指导我做错了什么吗?
方法一:
在 HttpLoading class 文件中,添加
import 'rxjs/add/operator/map';
方法二(针对systemjs):
如果您这样做,则不需要方法 1。
在main.ts
import 'rxjs';
在systemjs.config.js;
map: {
'rxjs': 'node_modules/rxjs',
},
packages: {
'rxjs': { main: 'bundles/Rx.min.js', defaultExtension: 'js' },
我正在尝试使用 Angular 2 路由器延迟加载来减少初始加载时间。
在我的应用程序中,我自定义了 Angular 的原始 Http 服务,以便在启动任何 http 请求时显示一个加载器,我在完成时隐藏它。
目前,我有一个 GlobalService(这是一个应用程序范围的单例),它保存加载栏的当前状态和扩展 Angular 原始 Http class 的 HttpLoading class。
在 AppModule 中,我将两者都添加到提供程序中,以便它们在应用程序范围内可用:
export function httpFactory(backend: XHRBackend, defaultOptions: RequestOptions, globalService: GlobalService) {
return new HttpLoading(backend, defaultOptions, globalService);
}
和
providers: [
GlobalService,
{
provide: Http,
useFactory: httpFactory,
deps: [XHRBackend, RequestOptions, GlobalService]
}
],
我有以下 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 { }
下面是我的 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();
});
}
}
下面是我的 GlobalService
从'@angular/core'导入{可注入,注入};
@Injectable() 导出 class 全球服务 { public isLoading: boolean = false; }
我尝试在下面创建 SharedModule,我认为我会在 AppModule 中注入它,它会解决问题:
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]
}]
};
}
}
并将我的 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 { 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 { }
但是没有用。每当我访问任何具有 http 调用的路由时,它都会在控制台上抛出错误。
例如,在 ngOnInit 的 HomeCompnent 中,我进行了一个 http 调用来获取一些数据。但是当我移动到这个组件时,我在控制台中显示以下错误。
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
任何人都可以指导我做错了什么吗?
方法一:
在 HttpLoading class 文件中,添加
import 'rxjs/add/operator/map';
方法二(针对systemjs):
如果您这样做,则不需要方法 1。
在main.ts
import 'rxjs';
在systemjs.config.js;
map: {
'rxjs': 'node_modules/rxjs',
},
packages: {
'rxjs': { main: 'bundles/Rx.min.js', defaultExtension: 'js' },