Prova a partire da qui:

codice:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Documento HTML</title>
<script type="text/javascript">
/*\
|*|
|*|    :: MiniDaemon ::
|*|
|*|    Revision #2 - September 26, 2014
|*|
|*|    https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
|*|    https://developer.mozilla.org/User:fusionchess
|*|
|*|    This framework is released under the GNU Lesser General Public License, version 3 or later.
|*|    http://www.gnu.org/licenses/lgpl-3.0.html
|*|
\*/
 
function MiniDaemon (oOwner, fTask, nRate, nLen) {
    if (!(this && this instanceof MiniDaemon)) { return; }
    if (arguments.length < 2) { throw new TypeError("MiniDaemon - not enough arguments"); }
    if (oOwner) { this.owner = oOwner; }
    this.task = fTask;
    if (isFinite(nRate) && nRate > 0) { this.rate = Math.floor(nRate); }
    if (nLen > 0) { this.length = Math.floor(nLen); }
}
 
MiniDaemon.prototype.owner = null;
MiniDaemon.prototype.task = null;
MiniDaemon.prototype.rate = 100;
MiniDaemon.prototype.length = Infinity;
 
    /* These properties should be read-only */
 
MiniDaemon.prototype.SESSION = -1;
MiniDaemon.prototype.INDEX = 0;
MiniDaemon.prototype.PAUSED = true;
MiniDaemon.prototype.BACKW = true;
 
    /* Global methods */
 
MiniDaemon.forceCall = function (oDmn) {
    oDmn.INDEX += oDmn.BACKW ? -1 : 1;
    if (oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false || oDmn.isAtEnd()) { oDmn.pause(); return false; }
    return true;
};
 
    /* Instances methods */
 
MiniDaemon.prototype.isAtEnd = function () {
    return this.BACKW ? isFinite(this.length) && this.INDEX < 1 : this.INDEX + 1 > this.length;
};
 
MiniDaemon.prototype.synchronize = function () {
    if (this.PAUSED) { return; }
    clearInterval(this.SESSION);
    this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this);
};
 
MiniDaemon.prototype.pause = function () {
    clearInterval(this.SESSION);
    this.PAUSED = true;
};
 
MiniDaemon.prototype.start = function (bReverse) {
    var bBackw = Boolean(bReverse);
    if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) { return; }
    this.BACKW = bBackw;
    this.PAUSED = false;
    this.synchronize();
};
</script>
<script type="text/javascript">
var demone = new (function () {

    function refreshEq (nIdx, nLength, bBackwards) {
        /*
        * Qui la tua equazione! In questo esempio ho messo solo una semplice
        * differenza tra la data di ogni chiamata e la data in cui il "demone"
        * e' stato avviato (in millisecondi). Cambia il tutto a tuo piacimento!
        */
        this.domNode.innerHTML = Date.now() - this.startedAt;

        /*
        * Debug. Rimuovi tranquillamente questa linea: serve solo a mostrarti i
        * parametri di cui puoi disporre in questa funzione...
        */
        this.domNode.innerHTML += "<br \/><br \/>Contatore: " + nIdx + "<br \/>Length: " + nLength + "<br \/>Direzione: " + (bBackwards ? "<em>retrograda</em>" : "<em>anterograda</em>");
    }

    /*
    * Page ready...
    */
    function initEq (oEvent) {
        document.getElementById("contenitore").appendChild(demone.owner.domNode);
    }

    var oDmn = new MiniDaemon(this, refreshEq, 1000, Infinity);

    this.startedAt = Date.now();
    this.domNode = document.createElement("span");

    /*
    * Forziamo la prima chiamata in maniera sincrona...
    */
    MiniDaemon.forceCall(oDmn);

    /*
    * Avviamo il demone
    */
    oDmn.start();

    window.addEventListener ? addEventListener("load", initEq, false) : window.attachEvent ? attachEvent("onload", initEq) : (onload = initEq);

    return oDmn;

})();
</script>
</head>

<body>
<div id="contenitore"></div>
<p><input type="button" onclick="demone.start(false /* optional */);" value="Start" /> <input type="button" onclick="demone.start(true);" value="Backward"> <input type="button" onclick="demone.pause();" value="Pause" /></p>
</body>
</html>