javascript - 如何从 GET 请求填充服务内的静态数组?
问题描述
我想要做的(我认为)非常简单。我正在构建一个 Web 应用程序,并且select
我想用来自远程 JSON 文件(GET 请求)的相同数据填充一些元素。我创建了一个服务,我想在那里填充一个静态数组并从我想要的任何组件中调用它。我认为我错过了一些至关重要的东西。
这是一些代码:
fetchData.service.ts
export interface Creditor {
id: number;
name: string;
}
@Injectable()
export class FetchDataService {
creditorsStaticArray: Creditor[] = [];
getCreditorsFromAPI() {
this.http.get<Creditor[]>(this.creditorsUrl)
.subscribe(
items => {
this.creditorsStaticArray = items;
}
);
}
getCreds() {
return this.creditorsStaticArray;
}
}
application-details.component.ts(组件之一)
export class ApplicationDetailsComponent implements OnInit {
loadedCreditors: Creditor[] = [];
constructor(private fetchDataService: FetchDataService) { }
ngOnInit() {
this.fetchDataService.getCreditorsFromAPI();
this.loadedCreditors = this.fetchDataService.getCreds();
}
}
我的解决方案是基于这个答案
任何帮助将非常感激!
解决方案
您的静态数组不能超出您的服务范围。但是,你不能真正拥有static
你的class scope
任何一个。
因为services
在 Angular 中singletons
,默认情况下,您的目标可以通过执行以下操作来实现:
@Injectable()
export class FetchDataService {
creditorsStaticArray: Creditor[] = [];
getCreditorsFromAPI() {
this.http.get<Creditor[]>(this.creditorsUrl)
.subscribe(
items => {
this.creditorsStaticArray = items;
}
);
}
getCreds() {
return this.creditorsStaticArray;
}
}
正如您已经提到的那样this.creditorsStaticArray
,这将立即起作用。您可能需要考虑将其重命名为creditorsCache
或类似的名称,并防止从服务外部直接访问它(通过 make 它private
),因为它不再是static
. 但是除了命名约定和访问限制之外,您正在实现您正在寻找的目标。
现在我将在底部添加一些最佳实践供您将来参考。
您在服务内订阅,而不是“明确”管理订阅。这不一定是坏事,因为默认值HttpClient
将在第一个结果后完成,但可能值得通过添加一个.pipe(first())
或.pipe(take(1))
(first
是take(1)
) 的别名来使其更明确。这样,如果您的 API 或您检索数据的方式发生更改,则会明确提醒这Observable
将采用 1 个值(整个数组)并自行完成,并将结果保存到变量中作为副作用。
您可能要考虑的不在subscribing
您的服务内部,而是将整个返回Observable
给您的组件,以便它传递并决定订阅的时刻。您仍然可以通过将变量放入
.pipe(
tap(data => { this.creditorsCache = data })
)
当您或您的组件(或您的 HTML 使用AsyncPipe
)订阅时;它会将其存储在其缓存中,您可以自动处理新传入的结果。
在上面的示例中,您仍然可以依靠您的caching
机制,通过将缓存数据作为Observable
. 幸运的是,RxJS 提供了大量的创建Observables
,这不应该太复杂!
一个简单的例子:
getCreditorsFromAPI(): Observable<Creditor[]> {
return this.http.get<Creditor[]>(this.creditorsUrl)
.pipe(
tap(data => this.creditorsCache = data)
)
);
}
getCreds(): Observable<Creditor[]> {
// You could also use this to invalidate your cache after 10 minutes!
if(this.creditorsCache.length > 0) {
return of(this.creditorsCache)
}
// Because I set the return type of this function, you will need to return a valid Observable. This makes your code predictable!
return this.getCreditorsFromAPI() // This will recreate your cache cause of the tap()!
}
在上面的示例中,您只会调用service.getCreds()
和管理组件中的订阅。每次您将 observable 重新分配给this.service.getCreds()
.
值得深思!我不会说有一种完美的做事方式,而且肯定有更多的方式可以通向比喻性的罗马。但我刚刚描述的内容肯定更多Reactive
,这是 Angular 的许多内部结构所依赖的。
推荐阅读
- testing - 如何在视频捕捉应用中测试贴纸和效果?
- c# - AzureCosmos DB - 使用 .Contains() 功能对一组搜索词实施查询
- javafx - 如何使光标在 JavaFX 文本字段中可见?
- c++ - 如何检查整数中是否恰好设置了一位?
- java - Java:如何打印 s3 存储桶的内容
- java - 使用 SurfaceViewGL 快速过滤视频
- c# - 需要有关此列表逻辑的帮助,不确定如何编写?
- python-3.x - python中的列表索引超出范围错误,为什么会发生?
- typescript - 如果我所有的导入都来自我自己的文件,我是否需要使用 TypeScript 3.8 的“导入类型”功能?
- python - Pandas,在尝试拆分数据时收到“TypeError:'list' object is not callable”