【问题标题】:How do I run a function on ngOnInit() only once and not again upon returning back from another routerLink?如何在 ngOnInit() 上只运行一次函数,而不是在从另一个 routerLink 返回时再次运行?
【发布时间】:2017-11-08 10:46:21
【问题描述】:

HomeComponent

ngOnInit()
{
    console.log('loaded');
    this.retrieveData();
}

retrieveData()
{
    // this.dataService.getData().subscribe(...);
}

组件加载时我正在检索数据。当用户单击另一个routerLink,例如SettingsComponent 并返回到HomeComponent 时,当然会再次调用该函数,因为该组件已再次加载。但是每次我返回组件时,它都会再次调用函数,这会创建太多不需要的 HTTP 请求。我需要防止这种情况并确保该函数仅在第一次被调用。我该怎么做呢?我应该使用其他一些组件生命周期挂钩吗?

【问题讨论】:

  • 我认为这应该是理想的行为。否则在用户关闭应用之前,您的数据不会改变。
  • 确实如此。但是,如果我在我的 observable 中使用间隔(比如数据每秒加载一次)并且如果我转到 SettingsComponent 并返回 HomeComponent,它会创建间隔的另一个实例,所以我每秒发出两个请求,如果过程重复,我每秒发送 50 个请求。

标签: angular ngoninit lifecycle-hook


【解决方案1】:

好的,我看到您正在使用service 来加载数据,这是一个好方法。

然后您可以简单地将数据缓存在某处,当您返回组件时检查缓存中的数据。我认为您可以将数据直接存储在您的服务中,这会将其保存在内存中,或者您可以将其放入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 -> providers

@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{ ... }

============================================== =

本地存储方法

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 ...
    }
}

这两种方法都有一个限制,即您不能处理大量数据,当然,如果您不想破坏正在使用您的应用的用户的浏览器 :)

【讨论】:

  • 感谢您解释得这么好。这似乎是我的问题的一个很好的解决方案。我会试试这个,让你知道会发生什么。
  • 我很高兴这是可以理解的。在这两种方法中,您都可以控制何时要从服务器重新加载数据
  • 我尝试了第一个解决方案,这正是我想要的。现在我将数据存储在内存中,而不是每次都检索它,应用程序中的许多功能现在响应速度比以前更快。真的很感激,我的朋友。
猜你喜欢
  • 2012-12-08
  • 1970-01-01
  • 2020-05-25
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-13
相关资源
最近更新 更多