2

I'm building an JS application where I'm using multiple timers (digital, analog). I would like to use a base class for the Timer with the functions: start, stop, update, etc.

Every time there is a timer created there are also new onChange event created. So when the timer ticks multiple instances get an update, not only the one where the timer is created in.

My question is: how can I bind and Timer instance the another class?

Timer class:

class Timer = {

    constructor() {
        this.seconds = 0;
    }

    start() {
        this.timer = setInterval(update, 25);
    }

    stop() {
        clearInterval(this.timer);
    }

    update() {

        this.seconds += 1;

        //emit data
        let event = new Event("timer-tick");
        event.detail = {
            seconds: seconds,
        }

        document.body.dispatchEvent(event);
    }
}

DigitalTimer class:

class DigitalTimer = {

    constructor() {
        this.timer = new Timer();
        this.handleEvent();
    }

    handleEvent() {

        $('body').on('timer-tick', function(e) {
            //tick, do somehting with it.
        });
    }

    start() {
        this.timer.start();
    }

    stop() {
        this.timer.stop()
    }
}
roapp
  • 530
  • 6
  • 17
  • 1
    I think all you need to do is not to fire timer-tick events *globally* on the `document.body` - instead register the callbacks with the individual `Timer` instance and then call these from your `update` method instead of using dom events. – Bergi Nov 30 '19 at 01:28
  • @Bergi Can you explain a little bit more; I don't understand how I then call the update function. – roapp Nov 30 '19 at 08:50
  • 1
    Keep an array of functions (or of complete `DigitalTimer` instaces) and call those `handleEvent` methods in the `update` method instead of firing a DOM event. Alternatitely, use `jQuery.Callbacks()` or some other event emitter. – Bergi Nov 30 '19 at 12:00

2 Answers2

1

There is a bind method on the Function prototype that does what you want.

start() {
    this.timer = setInterval(this.update.bind(this), 25);
}

On a side note, you shouldn't rely on setInterval or setTimeout to increment the time. Of course they are useful to make periodic calls, but the elapsed time isn't guaranteed. You can instead compare an initial Date object with a new one on each call.

challet
  • 870
  • 9
  • 21
0

I did get it working by binding an on and trigger event on a plain object. http://api.jquery.com/jQuery/#working-with-plain-objects

Working sample: https://jsfiddle.net/q5s6cud3/

class Timer {

  constructor() {

    let self = this;

    this.timer = setInterval(function() {
        self.update();
    }, 1000);   
  }

  update() {

     $(this).trigger('timer-tick');
    }
}

class DigitalTimer {

  constructor() {

    this.timer = new Timer();

    $(this.timer).on('timer-tick', function() {
        console.log('yes'); 
    });
  }
}

const digitalTImer = new DigitalTimer();
roapp
  • 530
  • 6
  • 17