Angular setTimeout работает слишком много раз - PullRequest
0 голосов
/ 16 октября 2019

У меня есть компонент просмотра журнала, реализованный в двух или более других компонентах. Эта программа просмотра журнала использует setTimeout для создания интервального цикла для извлечения данных из файла. Моя проблема заключается в том, что этот компонент импортируется в другие компоненты, таймер запускается для каждого компонента отдельно, таким образом, делая несколько операций чтения файлов в секунду.

Можно ли этого избежать, и таймер запускается только один раз, независимо от количества компонентов, использующих этотcomponent?

Вот код для компонента просмотра журнала, в котором создан интервал setTimeout:

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);
    }
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2019

Проблема в том, что this.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()
0 голосов
/ 16 октября 2019

Для решения этой проблемы Angular имеет Singleton services . Вы можете переместить setLogTimer() и logTimer в ваш LogsService.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...