angular 5 中的高阶服务
Higher order services in angular 5
在 angular 5 应用程序的开发过程中,我意识到我在重复创建用于通过 REST api 访问模型的服务,因此我认为将它们抽象化是有意义的进入以下工厂:
import { Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { action, observable } from 'mobx-angular';
import { ObservableArray } from 'mobx/lib/types/observablearray';
interface Parameters {
baseUrl: string;
name: string;
}
export interface BaseModel {
_id: string;
}
export interface RestCollectionServiceType<T> {
items: ObservableArray<T>;
get: () => Promise<void>;
create: (T) => Promise<void>;
remove: (T) => Promise<void>;
update: (T) => Promise<void>;
}
export default <T extends BaseModel>({ baseUrl, name }: Parameters) => {
class RestCollectionService {
@observable
items;
constructor(@Inject(HttpClient) private http: HttpClient) {
this.items = [];
}
@action
async get() {
const items = await this.http.get<T[]>(baseUrl)
.toPromise();
this.items.clear();
this.items.push(...items);
}
// ...
// Rest of the actions
// ...
}
return RestCollectionService;
};
那么一个示例服务如下:
import restCollectionServiceFactory, { RestCollectionServiceType, BaseModel } from '../utils/restCollectionServiceFactory';
export interface Team extends BaseModel {
name: string;
}
export interface TeamsService extends RestCollectionServiceType<Team> {
}
export const TeamsService = restCollectionServiceFactory<Team>({
baseUrl: '/api/teams',
name: 'Team',
});
一开始我在 DI 上遇到了一些困难,因为装饰器只能在 class 指令之前使用,所以我无法使我的任何服务(例如 TeamsService)可注入,但解决方法是使用在 RestCollectionServiceType 构造函数中注入装饰器,因为服务没有其他依赖项来解决它应该保存而不是使它们成为 Injectables,只需将它们添加到模块的 providers 数组中就足以满足我的理解
...
import { TeamsService } from './services/teams.service';
...
@NgModule({
declarations: [
...
],
imports: [
...
],
providers: [
...
TeamsService,
...
],
bootstrap: [
AppComponent,
],
})
export class AppModule { }
问题是这与 ng serve 一起工作正常,但是当我尝试构建时出现以下错误:ERROR in : Can't resolve all parameters for TeamsAdminPageComponent in .../src/app/pages/admin/teams/teamsAdmin.page.ts: (?).
成为 teamsAdmin.pate.ts 唯一依赖于 TeamsService 的组件
import {Component, Inject, OnInit} from '@angular/core';
import { TeamsService } from '../../../services/teams.service';
@Component({
selector: 'rm-admin-teams',
templateUrl: './teamsAdmin.page.html',
})
export class TeamsAdminPageComponent implements OnInit {
columns = ['name', 'countryCode'];
create = (team) => this.teamsService.create(team);
remove = (team) => this.teamsService.remove(team);
update = (team) => this.teamsService.update(team);
constructor(@Inject(TeamsService) private teamsService: TeamsService) { }
ngOnInit(): void {
this.teamsService.get();
}
}
如何解决?提前致谢。
您的 TeamsService
可能需要是 class 而不是接口,因此注入器可以创建它的实例。你还需要用@Injectable()
注释服务,否则注入器会抛出:
@Injectable()
export class TeamsService extends RestCollectionServiceType<Team> {
}
在 angular 5 应用程序的开发过程中,我意识到我在重复创建用于通过 REST api 访问模型的服务,因此我认为将它们抽象化是有意义的进入以下工厂:
import { Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { action, observable } from 'mobx-angular';
import { ObservableArray } from 'mobx/lib/types/observablearray';
interface Parameters {
baseUrl: string;
name: string;
}
export interface BaseModel {
_id: string;
}
export interface RestCollectionServiceType<T> {
items: ObservableArray<T>;
get: () => Promise<void>;
create: (T) => Promise<void>;
remove: (T) => Promise<void>;
update: (T) => Promise<void>;
}
export default <T extends BaseModel>({ baseUrl, name }: Parameters) => {
class RestCollectionService {
@observable
items;
constructor(@Inject(HttpClient) private http: HttpClient) {
this.items = [];
}
@action
async get() {
const items = await this.http.get<T[]>(baseUrl)
.toPromise();
this.items.clear();
this.items.push(...items);
}
// ...
// Rest of the actions
// ...
}
return RestCollectionService;
};
那么一个示例服务如下:
import restCollectionServiceFactory, { RestCollectionServiceType, BaseModel } from '../utils/restCollectionServiceFactory';
export interface Team extends BaseModel {
name: string;
}
export interface TeamsService extends RestCollectionServiceType<Team> {
}
export const TeamsService = restCollectionServiceFactory<Team>({
baseUrl: '/api/teams',
name: 'Team',
});
一开始我在 DI 上遇到了一些困难,因为装饰器只能在 class 指令之前使用,所以我无法使我的任何服务(例如 TeamsService)可注入,但解决方法是使用在 RestCollectionServiceType 构造函数中注入装饰器,因为服务没有其他依赖项来解决它应该保存而不是使它们成为 Injectables,只需将它们添加到模块的 providers 数组中就足以满足我的理解
...
import { TeamsService } from './services/teams.service';
...
@NgModule({
declarations: [
...
],
imports: [
...
],
providers: [
...
TeamsService,
...
],
bootstrap: [
AppComponent,
],
})
export class AppModule { }
问题是这与 ng serve 一起工作正常,但是当我尝试构建时出现以下错误:ERROR in : Can't resolve all parameters for TeamsAdminPageComponent in .../src/app/pages/admin/teams/teamsAdmin.page.ts: (?).
成为 teamsAdmin.pate.ts 唯一依赖于 TeamsService 的组件
import {Component, Inject, OnInit} from '@angular/core';
import { TeamsService } from '../../../services/teams.service';
@Component({
selector: 'rm-admin-teams',
templateUrl: './teamsAdmin.page.html',
})
export class TeamsAdminPageComponent implements OnInit {
columns = ['name', 'countryCode'];
create = (team) => this.teamsService.create(team);
remove = (team) => this.teamsService.remove(team);
update = (team) => this.teamsService.update(team);
constructor(@Inject(TeamsService) private teamsService: TeamsService) { }
ngOnInit(): void {
this.teamsService.get();
}
}
如何解决?提前致谢。
您的 TeamsService
可能需要是 class 而不是接口,因此注入器可以创建它的实例。你还需要用@Injectable()
注释服务,否则注入器会抛出:
@Injectable()
export class TeamsService extends RestCollectionServiceType<Team> {
}