这是我的Angular应用。我的应用程序将从API(临时在JSON文件中)获取数据,并显示在许多其他同级组件中。因此,我决定创建一个用于获取并存储数据的category.service.ts。在我的应用程序启动时,我首先使用APP_INITIALIZER来运行此服务。但是存在一个问题:该服务首先运行,AppComponent在服务获取数据之前运行。所以我的视图没有数据。
如果我单击将按钮路由到该组件,则一切运行正常。但是,当我通过URL路径或F5(刷新页面)转到该组件时,什么也没有显示
category.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class CategoryService {
DATA_CATEGORIES = 'assets/categories.json';
private _categories = [];
constructor(private http: HttpClient) {
}
get categories() {
return this._categories;
}
Init(): Promise<any> {
return new Promise<void>(resolve => {
this.http.get(this.DATA_CATEGORIES).subscribe(data => {
this._categories = Array.from(Object.keys(data), k => data[k]);
console.log("load data...");
});
resolve();
});
}
}
app.module.ts
export function initializeCategoryService(catService: CategoryService) {
return (): Promise<any> => {
return catService.Init();
}
}
@NgModule({
declarations: [
AppComponent,
HomeComponent,
StoriesFilterPipe,
ViewStoryComponent,
ViewCatComponent,
FrontEndComponent,
SearchComponent,
BackEndComponent,
CrudStoryFormComponent,
CrudStoryComponent,
JwPaginationComponent,
CrudCatComponent,
CrudCatFormComponent,
CrudCatSearchResultComponent,
CatListComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpClientModule,
],
providers: [
StoryService,
CategoryService,
{
provide: APP_INITIALIZER, useFactory: initializeCategoryService, deps: [CategoryService], multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
这是常见的情况-例如,您显示的页面尚不提供数据-例如在连接速度慢和连接不良的情况下,它甚至可以做更多的工作-连接断开并且未收到数据。
因此,您的页面应该不仅可以显示收到的数据,还可以显示另外两个状态:加载和错误。
(因此建议为“添加加载程序”。
我建议使用Observable
喜欢您的分类服务
import { Observable, Subject } from 'rxjs';
export class CategoryService {
private loadDataSub = new Subject<any>();
loadDataObservable$ = this.loadDataSub.asObservable();
emitLoadDataSuccess() {
this.loadDataSub.next();
}
Init(): Promise<any> {
return new Promise<void>(resolve => {
this.http.get(this.DATA_CATEGORIES).subscribe(data => {
this._categories = Array.from(Object.keys(data), k => data[k]);
console.log("load data...");
this.emitLoadDataSuccess(); // here we are emitting event
});
resolve();
});
}
}
并且在您的组件中
export class AppComponent implements OnInit {
constructor(private categoryService: CategoryService) {
this.categoryService.loadDataObservable$.subscribe(() => {
// here you can get data, this will only trigger when data is loaded from API
});
}
}
// data.service.ts
import { Injectable } from "@angular/core";
import { HttpClient, HttpClientModule } from "@angular/common/http";
@Injectable()
export class DataService {
private _categories = [];
constructor(private http: HttpClient) {}
get categories() {
return this._categories;
}
getData(): Promise<any[]> {
return new Promise<any[]>(resolve => {
this.http.get('https://api.myjson.com/bins/18qku4').subscribe(data => {
this._categories = Array.from(Object.keys(data), k => data[k]);
console.log("load data...");
resolve(this._categories);
});
});
}
}
// app.module.ts
import { NgModule, APP_INITIALIZER } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";
import { ListDataComponent } from "./list-data/list-data.component";
import { AppComponent } from "./app.component";
import { DataService } from "./data.service";
import { HttpClientModule } from "@angular/common/http";
import {DetailComponent} from './detail/detail.component'
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot([
{ path: "", component: ListDataComponent },
{ path: "detail", component: DetailComponent }
])
],
declarations: [AppComponent, ListDataComponent,DetailComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
//list-data.component.ts
import { Component, OnInit } from "@angular/core";
import { DataService } from "../data.service";
@Component({
selector: "app-list-data",
templateUrl: "./list-data.component.html",
styleUrls: ["./list-data.component.css"],
providers: [DataService],
})
export class ListDataComponent implements OnInit {
categories = [];
constructor(service: DataService) {
service.getData().then(data => {
debugger;
this.categories = data;
});
}
ngOnInit() {}
}
有替代方法可以解决此问题:
一个是您可以使用加载程序,可以显示该加载程序,直到服务调用结束。
第二,您可以使用* ngIf =“ categories?.length”,它将隐藏您的组件,直到您的服务调用结束。
我希望它能解决您的问题。