Delayed Execution

Queuing a task in the main event loop

When a task needs to be only briefly delayed, such that it runs after the current call chain returns, it can be added directly to the main thread's event queue rather than scheduled as a timeout:

function executeSoon(func) {
  Services.tm.mainThread.dispatch(func, Ci.nsIThread.DISPATCH_NORMAL);
}

Using nsITimers to schedule tasks

In instances where setTimeout() and setInterval() are unavailable, or insufficient, tasks can be scheduled with delays using nsITimer instances.

Note: If an nsITimer is garbage collected, it will be deactivated and its callbacks will not fire. A reference to the timer objects must be explicitly kept alive until that point.

Some example usages include:

  const Timer = Components.Constructor("@mozilla.org/timer;1", "nsITimer", "initWithCallback");

  function delay(timeout, func) {
    let timer = new Timer(function () {
      // Remove the reference so that it can be reaped.
      delete delay.timers[idx];

      func();
    }, timeout, Ci.nsITimer.TYPE_ONE_SHOT);

    // Store a reference to the timer so that it's not reaped before it fires.
    let idx = delay.timers.push(timer) - 1;
    return idx;
  }
  delay.timers = [];

  function repeat(timeout, func) {
    let timer = new Timer(function () {
      func();
    }, timeout, Ci.nsITimer.TYPE_REPEATING_SLACK);

    // Store a reference to the timer so that it's not reaped before it fires.
    let idx = delay.timers.push(timer) - 1;
    return idx;
  }
  repeat.timers = [];

  // Repeat a task every 1200ms
  repeat(1200, doAThing);

  // Do something 320ms from now
  delay(320, doSomething);