如何通过 GET 请求在服务中填充静态数组?
How can I populate a static array inside a service from a GET request?
我想做的(我认为)很简单。我正在构建一个 Web 应用程序,我想用来自远程 JSON 文件(GET 请求)的相同数据填充一些 select
元素。我创建了一个 service 并且我想在其中填充一个静态数组并从我想要的任何组件调用它。我想我错过了一些至关重要的东西。
这是一些代码:
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
。
因为 Angular 中的 services
默认为 singletons
,您的目标 objective 将通过执行以下操作来实现:
@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
。但是除了命名约定和访问限制器之外,您正在实现您正在寻找的目标。
现在我将在底部添加一些最佳实践以供您将来参考。
您是在您的服务内部进行订阅,而不是管理订阅 "explicitly"。这不一定是坏事,因为默认 HttpClient
将在第一个结果后完成,但可能值得通过添加 .pipe(first())
或 .pipe(take(1))
(first
是 take(1)
的别名)。这样,如果您的 API 或您检索数据的方式发生变化,则会明确提醒此 Observable
将采用 1 个值(整个数组)并自行完成,将结果保存到变量中side-effect.
您可能要考虑的不是 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()
并在您的组件中管理订阅。每次您将可观察对象重新分配给 this.service.getCreds()
.
时,它都会自动为您缓存
深思!我不会说有一种完美的做事方式,而且肯定有更多的方式可以通向象征性的罗马;但我刚才描述的内容肯定比 Reactive
多一点,这是 Angular 很多内部结构所依赖的。
Return 可从您的服务中观察到:
@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)
}
我想做的(我认为)很简单。我正在构建一个 Web 应用程序,我想用来自远程 JSON 文件(GET 请求)的相同数据填充一些 select
元素。我创建了一个 service 并且我想在其中填充一个静态数组并从我想要的任何组件调用它。我想我错过了一些至关重要的东西。
这是一些代码:
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
。
因为 Angular 中的 services
默认为 singletons
,您的目标 objective 将通过执行以下操作来实现:
@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
。但是除了命名约定和访问限制器之外,您正在实现您正在寻找的目标。
现在我将在底部添加一些最佳实践以供您将来参考。
您是在您的服务内部进行订阅,而不是管理订阅 "explicitly"。这不一定是坏事,因为默认 HttpClient
将在第一个结果后完成,但可能值得通过添加 .pipe(first())
或 .pipe(take(1))
(first
是 take(1)
的别名)。这样,如果您的 API 或您检索数据的方式发生变化,则会明确提醒此 Observable
将采用 1 个值(整个数组)并自行完成,将结果保存到变量中side-effect.
您可能要考虑的不是 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()
并在您的组件中管理订阅。每次您将可观察对象重新分配给 this.service.getCreds()
.
深思!我不会说有一种完美的做事方式,而且肯定有更多的方式可以通向象征性的罗马;但我刚才描述的内容肯定比 Reactive
多一点,这是 Angular 很多内部结构所依赖的。
Return 可从您的服务中观察到:
@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)
}