admin管理员组文章数量:1405502
This is my Angular App. My app will get data from API (temporarily in JSON file) and show in many another sibling ponent. So I decide to create a category.service.ts that I get and store data in. I using APP_INITIALIZER to run this service first when my app started. But there is a problem that: This service is running first, AppComponent runs before service get data done. So my view have empty of data.
If I click button routing to this ponent, everything run perfect. But when I go to this ponent by url path or F5(refresh page), nothing is shown
category.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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();
});
}
}
This is my Angular App. My app will get data from API (temporarily in JSON file) and show in many another sibling ponent. So I decide to create a category.service.ts that I get and store data in. I using APP_INITIALIZER to run this service first when my app started. But there is a problem that: This service is running first, AppComponent runs before service get data done. So my view have empty of data.
If I click button routing to this ponent, everything run perfect. But when I go to this ponent by url path or F5(refresh page), nothing is shown
category.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/mon/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 { }
Share
Improve this question
edited Feb 10, 2020 at 10:21
Nguyen Duc Binh
asked Feb 10, 2020 at 9:09
Nguyen Duc BinhNguyen Duc Binh
131 gold badge1 silver badge4 bronze badges
1
- try to use *ngIf in your app.ponent.html until your data is loaded – chana Commented Feb 10, 2020 at 9:17
3 Answers
Reset to default 2What I will suggest is to use Observable
like in your category service
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();
});
}
}
And In your ponent
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
});
}
}
This is mon case - i.e. you shows page while data is not avaliable yet - at slow and bad connections for instance, and it can do even more - connection was broken and data was nto recieved.
So, your page should be able to show not only data recieved, but also two another states: loading and error.
(So the advise is "add loader").
// data.service.ts
import { Injectable } from "@angular/core";
import { HttpClient, HttpClientModule } from "@angular/mon/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./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.ponent";
import { AppComponent } from "./app.ponent";
import { DataService } from "./data.service";
import { HttpClientModule } from "@angular/mon/http";
import {DetailComponent} from './detail/detail.ponent'
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
RouterModule.forRoot([
{ path: "", ponent: ListDataComponent },
{ path: "detail", ponent: DetailComponent }
])
],
declarations: [AppComponent, ListDataComponent,DetailComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
//list-data.ponent.ts
import { Component, OnInit } from "@angular/core";
import { DataService } from "../data.service";
@Component({
selector: "app-list-data",
templateUrl: "./list-data.ponent.html",
styleUrls: ["./list-data.ponent.css"],
providers: [DataService],
})
export class ListDataComponent implements OnInit {
categories = [];
constructor(service: DataService) {
service.getData().then(data => {
debugger;
this.categories = data;
});
}
ngOnInit() {}
}
There are alternatives to resolve this issue:
One is you can use a loader which you can display until the service call finishes.
Second is you can use *ngIf="categories?.length" which will keep your ponent hides until your service call finishes.
I hope it will resolve your issue.
本文标签: javascriptHow to load data service done first when app starting in Angular 8Stack Overflow
版权声明:本文标题:javascript - How to load data service done first when app starting in Angular 8 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744920374a2632256.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论