如何从 GET 请求填充服务中的静态数组?



我想做的(我认为)非常简单。我正在构建一个 Web 应用程序,我想使用远程 JSON 文件(GET 请求)中的相同数据填充一些select元素。我创建了一个服务,我想在其中填充一个静态数组,并从我想要的任何组件调用它。我认为我错过了一些至关重要的东西。
下面是一些代码:
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();
}
}

我的解决方案基于这个答案

任何帮助将不胜感激!

静态数组不能超出服务范围。但是,您也不能真正在class scope内拥有static

由于默认情况下singletonsAngular 中的services,因此可以通过执行以下操作来实现您的目标:

@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或类似名称,并防止从服务外部直接访问它(通过使其private),因为它不再static。但除了命名约定和访问限制器之外,您正在实现所需目标。


现在,我将在此处底部添加一些最佳实践,以备将来参考。

您是在服务中订阅,而不是"明确"管理订阅。这不一定是坏事,因为默认HttpClient将在第一个结果后完成,但可能值得通过添加.pipe(first()).pipe(take(1))来使其更明确(firsttake(1)的别名)。这样,如果您的 API 或检索数据的方式发生更改,则会明确提醒此Observable将获取 1 个值(整个数组)并自行完成,并将结果保存到变量作为副作用。

您可能要考虑的不是subscribing在您的服务内部,而是将整个Observable返回给您的组件,以便它传递并决定订阅的时刻。您仍然可以通过将变量的状态放在

.pipe(
tap(data => { this.creditorsCache = data })
)

当您或您的组件(或使用AsyncPipe的 HTML )订阅时;它会将其存储在缓存中,您可以自动处理新的传入结果。

在上面的示例中,您仍然可以依靠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()并管理组件中的订阅。每次您将可观察量重新分配给this.service.getCreds()时,它都会自动为您缓存。

发人深思的东西!我不会说有一种完美的做事方式,肯定有更多的方法可以导致比喻的罗马;但我刚才描述的肯定更Reactive这是 Angular 的许多内部结构所依赖的。

从您的服务返回可观察:

@Injectable()
export class FetchDataService {
creditorsStaticArray: Creditor[] = [];
getCreditorsFromAPI() {
return this.http.get<Creditor[]>(this.creditorsUrl);
}
}

在您的组件中:

loadedCreditors: Creditor[] = [];
ngOnInit() {
this.fetchDataService.getCreditorsFromAPI()
.subscribe(res => this.loadedCreditors = res)
}

最新更新