javascript - Angular - 从服务发送请求比从组件发送请求更好?
问题描述
我想知道我是否应该从角度服务发送请求?还是我应该直接从组件发送它?
第一种方法:
餐厅服务.ts
getRestaurants(): Promise<_Restaurant[]> {
return this.get("/restaurants").toPromise();
};
餐厅.component.ts
loadRestaurants = async () => {
try {
this.restaurants = await this.restaurantService.getRestaurants();
} catch (exception) {
console.log(JSON.stringify(exception, null, 2));
}
}
这意味着请求是通过组件触发的。
第二种方法:
餐厅服务.ts
async getRestaurants(): Promise<_Restaurant[]> {
try {
const response: _Restaurant[] = await this.get("/restaurants").toPromise() as _Restaurant[];
return response;
} catch (exception) {
throw new Error(exception);
}
};
餐厅.component.ts
loadRestaurants = async () => {
try {
this.restaurants = await this.restaurantService.getRestaurants();
} catch (exception) {
console.log(JSON.stringify(exception, null, 2));
}
}
这意味着请求是从服务中触发的,然后将响应作为承诺返回
那么最好的方法是什么?如果是第二种方法,是否可以从服务中捕获错误并将其扔给组件?
解决方案
正如 Angular 文档所说,最好在服务中包含该逻辑,看看这个:
class Service {
constructor(public http: HttpClient) { }
getRestaurants(): Observable<Restaurant> {
return this.http.get<{ /* Specify HTTP response schema */ }>(url).pipe(
// Transformation to actual Restaurants at one place
map(data => data.map(restaurant => new Restaurant()),
// Handle error
catchError(err => {
logError(err);
throw err;
// Or...
return of([]); // Mock data not to crash app
}),
// If multiple subscription are made to same source, it won't do multiple http calls
shareReply(1),
);
}
}
class Component {
restaurants: Restaurant[] = [];
ngOnInit(): void {
// Prefered way
this.restaurants$ = this.service.getRestaurants().pipe(
// If, you pass error down, you'll be able to hendle it here...
catchError(err => {
return of([]);
}),
);
// Alternative
this.cleanUp = this.service.getRestaurants().subscribe(restaurants => {
this.restaurants = restaurants;
});
}
ngOnDestroy(): void {
this.cleanUp.unsubscribe();
}
}
HTML
<!-- Observable -->
<div *ngFor="let restaurant of restaurants$ | async">
{{restaurant | json}}
</div>
<!-- Non-Observable -->
<div *ngFor="let restaurant of restaurants">
{{restaurant | json}}
</div>
我已将您的代码从 promise 转换为 observables,因为 observables 是使用 Angular 的最大好处之一。Observables 可以被取消,在模板中可读性很好,还有很多其他我可能有一天会想到的东西。
Observables 非常强大,您可以始终拥有基于其他 observable 的新鲜信息。看看吧,也许会给你一些想法……
interface ApiResponse<type> {
awaitingNewValues: boolean;
error: null | any;
response: type;
}
class Service {
currentRestaurantID = new BehaviourSubject(1);
currentRestaurantInfo: Observable<ApiResponse<Restaurant>>;
constructor(private http: HTTPClient) {
let latestRestaurants: ApiResponse<Restaurant | undefined> = {
awaitingNewValues: true,
error: null,
response: [],
};
currentRestaurantInfo = this.currentRestaurantID.pipe(
switchMap(restaurantID => {
return concat(
// This will notify UI that we are requesting new values
of(Object.assign({}, latestRestaurants, { awaitingNewValues: true })),
// The actual call to API
this.http.get(`${apiUrl}/${restaurantID}`).pipe(
// Wrap response in metadata
map(restaurant => {
return {
awaitingNewValues: false,
error: null,
response: restaurant,
}
}),
// Notify UI of error & pass error
catchError(err => {
return of({
awaitingNewValues: true,
error: err,
response: undefined,
});
}),
),
);
}),
// Save last response to be used in next api call
tap(restaurants => this.latestRestaurants = restaurants),
// Prevent calling API too many times
shareReplay(1),
);
}
}
推荐阅读
- c# - 根据用户配置 JwtBearerOptions IssuerSigningKey
- c# - 无法将客户数据放入 sparkpost 电子邮件
- javascript - 警告非确定性路由危险:尝试创建页面:[...] 已存在
- microsoft-graph-api - 是否有可用于获取频道/通话信息(例如参与者列表)的 Teams API 端点?
- java - 将 JSON 属性解析为字符串属性列表
- c# - 如何控制 WPF exe 文件版本
- sql - 关于 ORACLE SQL 查询
- c++ - 如果使用嵌套命名空间,如何转发声明 C++ 结构?
- kubernetes - 在 WSL 上为 Ceph 创建一个新的 /dev/sd{b,c,d}
- javascript - 从primeng p-editor的工具栏中删除选项卡-不适用于反应形式