Global Timer in Javascript with Multiple Callbacks

2019-02-23 16:06发布

I want to create a global timer object in javascript and then be able to add callbacks to it on the fly. This way I can just use one global timer in my script to execute all actions at a certain interval rather than wasting resources by using multiples.

This is how I want to be able to piece things together:

var timer = new function() { 
 clearInterval( this.interval );

 //[1] At this point I want the Callbacks to be run

 var self = this;
 setTimeout(function() {self.timer()}, 200);
}

function otherObject = new function() {
    //When created I want to bind my object's function called cb to the global timer at [1]
}

otherObject.prototype.cb = function() {
    //Stuff that should be done every time the timer is run
}

var someObject = new otherObject();

How would I make it possible bind any number functions (most of which are functions within other objects) to run at the interval of my timer on the fly?

3条回答
混吃等死
2楼-- · 2019-02-23 16:33

Just a slightly modified version of aekeus approach. Now with pause- & resumable timers, third arguments and a faster callbacks-loop:

function Interval(callback, freq) {

    // array of callback functions
    var args = arguments,
        callbacks = [callback],
        paused = false;

    // register the global timer
    var id = setInterval(function () {
        if(paused) return;
        var len = callbacks.length,
            i = len;
        while(i--) callbacks[len - 1 - i].apply(Interval, Array.prototype.slice.call(args, 2, args.length));
    }, freq);

    // return a Global Timer object
    return {
        id: function () {
            return id;
        },
        add: function (cb) {
            callbacks.push(cb);
        },
        clear: function () {
            if (id === null) return;
            clearInterval(id);
            id = null;
        },
        pause: function(){
            paused = true;
        },
        resume: function(){
            paused = false;
        }
    };
}

You can pass in extra-arguments like with default setInterval's (even in IE lt 9):

function callback(date) {
    console.log(date);
}

var interval = Interval(callback, 1000, new Date);

Usage example:

var interval = Interval(function () {
    console.log("init", new Date);
}, 1000);

interval.add(function () {
    console.log("a", new Date);
});

interval.add(function () {
    console.log("b", new Date);
});

document.onmousedown = interval.pause;
document.onmouseup = interval.resume;
查看更多
该账号已被封号
3楼-- · 2019-02-23 16:43

Have the interval fire an event. The subscribing functions can listen to the event (or not) and choose to fire or not according to their own logic.

The jQuery way of doing this would be:

(function() {
  setInterval(function() {
    $(document).trigger('heartbeat-of-the-universe');
  }, 200);
})();

Then later inside otherObject ...

$(document).bind('heartbeat-of-the-universe', this.cb);

There are obviously other ways of implementing events.

As the google link in the comments notes, this isn't the option with the highest performance. It is flexible and relatively forgiving however.

查看更多
放荡不羁爱自由
4楼-- · 2019-02-23 16:47

Create a GlobalTimer object and give it the ability to register callback functions and cancel itself.

function makeGlobalTimer(freq) {
  freq = freq || 1000;

  // array of callback functions
  var callbacks = [];

  // register the global timer
  var id = setInterval(
    function() {
      var idx;
      for (idx in callbacks) {
        callbacks[idx]();
      }
    }, freq);

  // return a Global Timer object
  return {
    "id": function() { return id; },
    "registerCallback": function(cb) {
      callbacks.push(cb);
    },
    "cancel": function() {
      if (id !== null) {
        clearInterval(id);
        id = null;
      }
    }
  };
}

var gt = makeGlobalTimer(500);
gt.registerCallback(function() {
                      console.log("a");
                    });

gt.registerCallback(function() {
                      console.log("b");
                    });

setTimeout(function() { gt.cancel(); }, 5000);
查看更多
登录 后发表回答