Javascript 角度设置超时运行次数太多

Javascript 角度设置超时运行次数太多,javascript,angular,intervals,Javascript,Angular,Intervals,我在两个或多个其他组件中实现了日志查看器组件。此日志查看器使用setTimeout创建间隔循环,以从文件中获取数据。我的问题是,由于该组件是在其他组件中导入的,因此计时器会分别为每个组件运行,从而每秒读取多个文件 是否可以避免这种情况,并且无论使用此组件的组件数量如何,都只运行计时器一次 下面是创建setTimeout interval的log viewer组件的代码: import { Component, ElementRef, OnInit, ViewChild } from '@angu

我在两个或多个其他组件中实现了日志查看器组件。此日志查看器使用setTimeout创建间隔循环,以从文件中获取数据。我的问题是,由于该组件是在其他组件中导入的,因此计时器会分别为每个组件运行,从而每秒读取多个文件

是否可以避免这种情况,并且无论使用此组件的组件数量如何,都只运行计时器一次

下面是创建setTimeout interval的log viewer组件的代码:

import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { LogsService } from '../../services/logs.service';
import { HelperService } from '../../services/helper.service';

@Component({
    selector: 'app-logger',
    templateUrl: './logger.component.html',
    styleUrls: ['./logger.component.scss']
})
export class LoggerComponent implements OnInit {
    @ViewChild('scroller', {static: false}) scroller: ElementRef;

    logClassName: string = 'logs shadow close';
    logs: string = '';
    logTS: number = 0;
    logTimer;
    scrollTop: number = 0;

    constructor(
        private logsService: LogsService,
        private h: HelperService
    ){}

    ngOnInit(): void {
        this.getLogs();
    }

    ngOnDestroy(): void {
        if (this.logTimer) window.clearTimeout(this.logTimer);
    }

    toggle(type){
        switch (type)
        {
            case 'open': this.logClassName = 'logs shadow open'; break;
            case 'close': this.logClassName = 'logs shadow close'; break;
            case 'full': this.logClassName = 'logs shadow full'; break;
        }
    }

    getLogs(){
        this.logsService.fetch(this.logTS).subscribe(
            response => {
                this.logs += response.data.join('');
                this.logTS = response.ts;

                window.setTimeout(() => {
                    this.scrollTop = this.scroller.nativeElement.scrollHeight;
                }, 100);

                this.setLogTimer();
            },
            error => {
                this.h.lg('unable to fetch logs', 'error');
                this.logs = '<p>Unable to fetch logs</p>';

                this.setLogTimer();
            }
        );
    }

    setLogTimer(){
        if (this.logTimer) window.clearTimeout(this.logTimer);

        this.logTimer = window.setTimeout(() => {
            this.getLogs();
        }, 1000);
    }
}
从'@angular/core'导入{Component,ElementRef,OnInit,ViewChild};
从“../../services/logs.service”导入{LogsService};
从“../../services/helper.service”导入{HelperService};
@组成部分({
选择器:“应用程序记录器”,
templateUrl:'./logger.component.html',
样式URL:['./logger.component.scss']
})
导出类LoggerComponent实现OnInit{
@ViewChild('scroller',{static:false})scroller:ElementRef;
logClassName:string='logs shadow close';
日志:字符串=“”;
logTS:number=0;
日志计时器;
scrollTop:number=0;
建造师(
私人日志服务:日志服务,
私人h:助手服务
){}
ngOnInit():void{
这是getLogs();
}
ngOnDestroy():void{
if(this.logTimer)window.clearTimeout(this.logTimer);
}
切换(类型){
开关(类型)
{
大小写“打开”:this.logClassName='logs shadow open';break;
案例“close”:this.logClassName='logs shadow close';break;
大小写“full”:this.logClassName='logs shadow full';break;
}
}
getLogs(){
this.logsService.fetch(this.logTS).subscribe(
响应=>{
this.logs+=response.data.join(“”);
this.logTS=response.ts;
window.setTimeout(()=>{
this.scrollTop=this.scroller.nativeElement.scrollHeight;
}, 100);
这个.setLogTimer();
},
错误=>{
this.h.lg('无法获取日志','错误');
this.logs='无法获取日志;
这个.setLogTimer();
}
);
}
setLogTimer(){
if(this.logTimer)window.clearTimeout(this.logTimer);
this.logTimer=window.setTimeout(()=>{
这是getLogs();
}, 1000);
}
}

要解决此问题,必须使用Angular。您可以在
LogsService
中移动
setLogTimer()
logTimer
,问题在于
这一点。logTimer与组件实例相关联,每个实例的设置都不一样,而且永远不会取消。解决方案是使用一些共享服务来执行文件读取,就像

@Injectable(provideIn:'root')
export class SomeService{

    setLogTimer(){
            if (this.logTimer) window.clearTimeout(this.logTimer);

            this.logTimer = window.setTimeout(() => {
                this.getLogs();
            }, 1000);
        }

}
然后在组件中使用此服务,如

this.someService.setLogTimer()

另一种方法是使用“rxjs”计时器创建一个可观察对象,并订阅/取消订阅,参见中的示例