Как запустить функцию в ngOnInit() только один раз, а не снова при возврате из другого routerLink?
HomeComponent
ngOnInit()
{
console.log('loaded');
this.retrieveData();
}
retrieveData()
{
// this.dataService.getData().subscribe(...);
}
Я получаю данные при загрузке компонента. Когда пользователь нажимает на другой routerLink
, например, SettingsComponent
и возвращается к HomeComponent
, функция, конечно, вызывается снова, потому что компонент загружен снова. Но каждый раз, когда я возвращаюсь обратно к компоненту, он снова вызывает функцию, что создает слишком много нежелательных HTTP-запросов. Мне нужно предотвратить это и убедиться, что функция вызывается только в первый раз. Как мне это сделать? Должен ли я использовать какой-то другой компонент жизненного цикла?
1 ответ
Хорошо, я вижу, что вы используете сервис для загрузки данных, что является хорошим способом.
Затем вы можете просто где-то кешировать данные, а когда вернетесь к компоненту, проверить кеш на эти данные. Я думаю, что вы можете хранить данные непосредственно в вашем сервисе, который будет хранить их в памяти, или вы можете поместить их в localStorage
Итак, первый вариант будет выглядеть так:
data.service.ts
export class DataService {
private data: any[];
setData(data:any[]){
this.data = data;
}
getData(){
return this.data || [];
}
hasData(){
return this.data && this.data.length;
}
getData(){
// your implementation here
}
}
затем внутри HomeComponent
retrieveData(){
if(this.dataService.hasData()){
// this will get the data which was previously stored in the memory
// and there will be no HTTP request
let data = this.dataService.getData();
// do something with data now ...
}else{
// old code
this.dataService.getData().subscribe(response => {
// but this time safe the data for future use
this.dataService.setData(response.data);
}, error => {
// handle errors
});
}
}
ВАЖНО: если вы используете этот подход, вы должны сделать свой сервис глобальным при объявлении его в app.module.ts -> provider
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [
DataService <---------- SEE HERE
],
bootstrap: [AppComponent]
})
export class AppModule { }
а потом не делать этого:
@Component({
selector: 'home',
templateUrl: '...',
styleUrls: ['...'],
providers: [
DataService <---- THEN DON'T put in component's providers
]
})
export class HomeComponent{ ... }
=============================================
Подход localStorage
HomeComponenet
retrieveData()
{
let data = localStorage.getItem('yourDataName');
if (data === null){
// old code
this.dataService.getData().subscribe(response => {
// but this time safe the data for future use in localStorage
localStorage.setItem('yourDataName', response.data);
}, error => {
// handle errors
});
} else {
// seems that you already loaded this data
// do something with this data ...
}
}
Оба подхода имеют ограничение, заключающееся в том, что вы не можете работать с огромными объемами данных, конечно, если вы не хотите взрывать браузеры пользователей, которые используют ваше приложение:)