服务 angular 与自定义 class?
Service angular vs custom class?
我想知道创建服务的方法。
我从服务器 RegistryItem[]
获取数据为 JSON。
选择哪种方式来创建处理每个 RegistryItem
的服务或创建包含 delete()
、edit()
等所有逻辑的 class RegistryItem
?
class RegistryService {
edit(registry);
delete();
drawRegister();
}
或
class RegistryItem {
edit();
delete();
drawRegister();
// Other logic for drawing registry
}
换句话说,我应该将响应项包装成逻辑 class 还是更好地将逻辑移至特定服务?
最佳实践要求您将模型和业务逻辑分开。你的模型(类型或接口)应该只执行数据没有任何行为,你让可注入services
操纵你的模型:
export interface RegistryItem {
id: number;
// other related properties
}
并且您的服务应包含与操纵您的 RegistryItem
相关的逻辑:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class RegistryItemService {
// your backend base api url
baseUrl = 'http://localhost:3000/api';
getAll() : Observable<RegistryItem[]> {
return this.http.get<RegistryItem[]>(this.baseUrl+ '/registry-items')
}
update(item: RegistryItem) : Observable<RegistryItem> {...}
create(item: RegistryItem) : Observable<any> {...}
delete(id: number) : Observable<any> {...}
drawRegister() {...};
}
此服务可以稍后注入并在您的组件中使用,如下所示
注册表-item.component.ts
@Component({
selector: 'app-registry-item',
templateUrl: './registry-item.component.html',
})
export class RegistryItemComponent {
registryItems: RegistryItem[] = [];
constructor(private service: RegistryItemService ) {
this.service.getAll().subscribe(res=> {
this.registryItems = res;
},
err=> console.error(err)
);
}
}
注册表-item.component.html
<div>
<h1>Registry items<h1/>
<!--
show your data in a list or table or whatever you like
-->
<ul>
<li *ngFor="let i of registryItems">
<span>{{i.id}} </span>
<!-- show other info
<span>{{i.name}} </span> -->
</li>
</ul>
</div>
我会选择单例服务。
因此,无论您将其注入到应用程序的哪个位置,您始终共享同一个服务实例(没有理由创建该服务的多个实例)。
我们可以通过在可注入装饰器的“root”或“plaform”中提供它来实现这一点(参见下面的示例):
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Employee } from '../shared/employee';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class RestApiService {
// Define API
apiURL = 'http://localhost:3000';
constructor(private http: HttpClient) { }
/*========================================
CRUD Methods for consuming RESTful API
=========================================*/
// Http Options
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
}
// HttpClient API get() method => Fetch employees list
getEmployees(): Observable<Employee> {
return this.http.get<Employee>(this.apiURL + '/employees')
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API get() method => Fetch employee
getEmployee(id): Observable<Employee> {
return this.http.get<Employee>(this.apiURL + '/employees/' + id)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API post() method => Create employee
createEmployee(employee): Observable<Employee> {
return this.http.post<Employee>(this.apiURL + '/employees', JSON.stringify(employee), this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API put() method => Update employee
updateEmployee(id, employee): Observable<Employee> {
return this.http.put<Employee>(this.apiURL + '/employees/' + id, JSON.stringify(employee), this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API delete() method => Delete employee
deleteEmployee(id){
return this.http.delete<Employee>(this.apiURL + '/employees/' + id, this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// Error handling
handleError(error) {
let errorMessage = '';
if(error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(errorMessage);
}
}
这个例子不是我出的,我是从这个guide拿来的。
但我很确定我会实现或多或少完全相同的代码,所以只是复制它。
只是对代码的一些评论:
我不会在服务中定义 API URL 端点,您可能需要从不同的环境(例如 local/QA/prod)访问不同的 API,所以我会将端点作为字符串存储在由 Angular CLI 自动创建的环境文件(例如 environment.[targetENV].ts
)中。当然,如果您计划从每个 ENV 访问始终相同的 API,您可以完全按照示例中的方式进行。否则,您可以为您拥有的每个环境文件分配一个不同的 API 端点,然后将其导入您的服务以使用它。
ENV文件截图:
这是您可能希望如何构建 env 文件的示例。
export const environment = {
production: false,
API_URL: 'http:/blabla.com/blabla/api',
API_EMPLOYEE: 'http://test.api.com/test-api/api',
};
如果您的代码可能用在运行多个 Angular 应用程序的一个网页上,您可能希望在“平台”而不是“根目录”中提供它。 100%只使用一个服务实例。
要实现这一点,只需更改可注入装饰器:
@Injectable({
providedIn: 'root'
})
至:
@Injectable({
providedIn: 'platform'
})
我想知道创建服务的方法。
我从服务器 RegistryItem[]
获取数据为 JSON。
选择哪种方式来创建处理每个 RegistryItem
的服务或创建包含 delete()
、edit()
等所有逻辑的 class RegistryItem
?
class RegistryService {
edit(registry);
delete();
drawRegister();
}
或
class RegistryItem {
edit();
delete();
drawRegister();
// Other logic for drawing registry
}
换句话说,我应该将响应项包装成逻辑 class 还是更好地将逻辑移至特定服务?
最佳实践要求您将模型和业务逻辑分开。你的模型(类型或接口)应该只执行数据没有任何行为,你让可注入services
操纵你的模型:
export interface RegistryItem {
id: number;
// other related properties
}
并且您的服务应包含与操纵您的 RegistryItem
相关的逻辑:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class RegistryItemService {
// your backend base api url
baseUrl = 'http://localhost:3000/api';
getAll() : Observable<RegistryItem[]> {
return this.http.get<RegistryItem[]>(this.baseUrl+ '/registry-items')
}
update(item: RegistryItem) : Observable<RegistryItem> {...}
create(item: RegistryItem) : Observable<any> {...}
delete(id: number) : Observable<any> {...}
drawRegister() {...};
}
此服务可以稍后注入并在您的组件中使用,如下所示
注册表-item.component.ts
@Component({
selector: 'app-registry-item',
templateUrl: './registry-item.component.html',
})
export class RegistryItemComponent {
registryItems: RegistryItem[] = [];
constructor(private service: RegistryItemService ) {
this.service.getAll().subscribe(res=> {
this.registryItems = res;
},
err=> console.error(err)
);
}
}
注册表-item.component.html
<div>
<h1>Registry items<h1/>
<!--
show your data in a list or table or whatever you like
-->
<ul>
<li *ngFor="let i of registryItems">
<span>{{i.id}} </span>
<!-- show other info
<span>{{i.name}} </span> -->
</li>
</ul>
</div>
我会选择单例服务。 因此,无论您将其注入到应用程序的哪个位置,您始终共享同一个服务实例(没有理由创建该服务的多个实例)。 我们可以通过在可注入装饰器的“root”或“plaform”中提供它来实现这一点(参见下面的示例):
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Employee } from '../shared/employee';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class RestApiService {
// Define API
apiURL = 'http://localhost:3000';
constructor(private http: HttpClient) { }
/*========================================
CRUD Methods for consuming RESTful API
=========================================*/
// Http Options
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
}
// HttpClient API get() method => Fetch employees list
getEmployees(): Observable<Employee> {
return this.http.get<Employee>(this.apiURL + '/employees')
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API get() method => Fetch employee
getEmployee(id): Observable<Employee> {
return this.http.get<Employee>(this.apiURL + '/employees/' + id)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API post() method => Create employee
createEmployee(employee): Observable<Employee> {
return this.http.post<Employee>(this.apiURL + '/employees', JSON.stringify(employee), this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API put() method => Update employee
updateEmployee(id, employee): Observable<Employee> {
return this.http.put<Employee>(this.apiURL + '/employees/' + id, JSON.stringify(employee), this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// HttpClient API delete() method => Delete employee
deleteEmployee(id){
return this.http.delete<Employee>(this.apiURL + '/employees/' + id, this.httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
)
}
// Error handling
handleError(error) {
let errorMessage = '';
if(error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(errorMessage);
}
}
这个例子不是我出的,我是从这个guide拿来的。 但我很确定我会实现或多或少完全相同的代码,所以只是复制它。
只是对代码的一些评论:
我不会在服务中定义 API URL 端点,您可能需要从不同的环境(例如 local/QA/prod)访问不同的 API,所以我会将端点作为字符串存储在由 Angular CLI 自动创建的环境文件(例如 environment.[targetENV].ts
)中。当然,如果您计划从每个 ENV 访问始终相同的 API,您可以完全按照示例中的方式进行。否则,您可以为您拥有的每个环境文件分配一个不同的 API 端点,然后将其导入您的服务以使用它。
ENV文件截图:
这是您可能希望如何构建 env 文件的示例。
export const environment = {
production: false,
API_URL: 'http:/blabla.com/blabla/api',
API_EMPLOYEE: 'http://test.api.com/test-api/api',
};
如果您的代码可能用在运行多个 Angular 应用程序的一个网页上,您可能希望在“平台”而不是“根目录”中提供它。 100%只使用一个服务实例。
要实现这一点,只需更改可注入装饰器:
@Injectable({
providedIn: 'root'
})
至:
@Injectable({
providedIn: 'platform'
})