0

Is there anything like a "dispose" function or "thread shutdown hook" for a specific thread running via setInterval?

Don Rhummy
  • 24,730
  • 42
  • 175
  • 330
  • 2
    Get threads out of your mind. `setInterval` does not work by threads and, the majority of the time, Javascript has no concept of threading. – lonesomeday Jan 11 '12 at 23:36

2 Answers2

2
(function () {
    var _setInterval = window.setInterval,
        _clearInterval = window.clearInterval;



    window.setInterval = function (fn, time) {
        //Implement your hooks here, hopefully without side effects
        return _setInterval(fn, time);
    };

    window.clearInterval = function (id) {
        //Implement your hooks here, hopefully without side effects
        return _clearInterval(id);
    };

})()

From comments it became clear that you don't need hooking because you are in an environment that you control. In that case you can just write wrapper functions like myClearInterval etc. with same principle.

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • A good start, except that `setInterval()` accepts zero or more optional arguments after the delay. Might be worth doing something like `_setInterval.apply(window, arguments)` instead (`arguments` in this case will contain all the arguments passed to `window.setInterval`). – Lachlan McDonald Jan 11 '12 at 23:53
  • @LachlanMcDonald I didn't do that because IE7 doesn't have apply/call on host objects. And the optional arguments are non standard AFAIK. Besides, it is trivial to do with currying anyway. – Esailija Jan 11 '12 at 23:56
  • I essentially did something like this (a wrapper for the clearInterval/setInterval functions). Thanks! – Don Rhummy Jan 11 '12 at 23:57
  • @Esailija. Ah, I didn't know either of those two things. I suppose if Don's code isn't in an environment where those extra parameters are being used, it shouldn't matter a great deal anyway. – Lachlan McDonald Jan 12 '12 at 00:00
  • How sure are you that you can always replace `window.clearInterval()` and `window.setInterval()` with your own version in all browsers now and in the future? Isn't there more and more movement over time to protect some of these system functions so they can't be replaced? – jfriend00 Jan 12 '12 at 00:02
  • @jfriend00 [] and {} were protected because of XSS, I am not aware of anything else (and even then, those are special syntax not just a property in `window`). About the future, I can't predict it :P – Esailija Jan 12 '12 at 00:05
  • @jfriend00 - while I think it's pretty safe to do that, I actually did not replace the function. Instead I made another function that "wraps" my call to clearInterval and also executes other code and then I call that instead of calling clearInterval directly. So there's no risk of it not working with any browser. – Don Rhummy Jan 12 '12 at 00:08
  • The reason I ask is because I've found some properties of the window object (I think it was `window.screen`) are protected in some newer browsers and cannot be shadowed or replaced with your own version. That led me to believe that this might be a general trend in some browsers. – jfriend00 Jan 12 '12 at 00:14
  • @DonRhummy - Esailija did replace `window.setInterval()` and `window.clearInterval()` with another function which is what I was writing about If those properties were read-only in any browser or some time in the future, this strategy would not work. Good to know you were not doing that yourself Don. – jfriend00 Jan 12 '12 at 00:17
  • @jfriend00 Yeah that's good example, chrome allows overwriting it but firefox doesn't. I can't predict the future but I can say for now that in firefox, ie7 and chrome this works (didn't bother testing anything else). It's not like you need to do this anyway, unless you wanna hook into some page you don't own and see when they call clearInterval etc.. For your own code you can just use wrappers. – Esailija Jan 12 '12 at 00:20
1

First off, as others have said, there are no threads in javascript (other than WebWorkers, but I don't think that's what you're talking about here.

All setInterval() does is call a function on a repeated basis - it isn't a thread, it isn't pre-emptive and it won't get called until all other javascript has stopped executing so the timer event can be processed. If your issue is that you want to dispose of some state when the interval is cleared so it will no longer be called, then you have two options:

1) You can use a javascript closure to store your state and when the interval is cleared, the closure will automatically be released.

2) You can create your own version of clearInterval that both clears the interval timer and cleans up your state.

The javascript closure option would look like this:

var interval;
function startMyInterval() {
    // sample state variables
    var state1 = 0;
    var state2 = [];
    var state3 = {whatever: "whatever"};

    interval = setInterval(function() {
        // javascript code here that can reference state1, state2 and state3
    }, 1000);
}

// then some time later when you want to stop the interval, you call clearInterval
// the closure is released and all the state variables are freed automatically
clearInterval(interval);

Or, if you want to do any other things when the interval is cleared, you can make your own function for clearing the interval that will not only release the closure, but also let you run any other code.

function clearMyInterval() {
    clearInterval(interval);
    // do any other cleanup you want to when the interval is stopped
}

I see that others have suggested hooking/replacing window.clearInterval() with your own function, but I prefer not to do that because it is unclear if that is a supported/documented feature and some system functions (more and more of them over time) are becoming protected so they cannot be replaced.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @DonRhummy - You apparently misunderstand how `setInterval()` and `setTimeout()` work. They absolutely will NOT fire until all other javascript in the page is done running. They work via an event queue and the next timer event ONLY starts javascript executing when the currently running javascript in the page finishes and the javascript engine can then fetch the next event in the queue and start that thread of execution. See this post for more of an explanation: http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649. – jfriend00 Jan 12 '12 at 00:07
  • That's pretty close to what I did. – Don Rhummy Jan 12 '12 at 00:09
  • any idea why they chose to do that instead of using threads? (I am not saying, "instead of exposing threads," just simply using multiple threads instead of one thread and not giving direct access to the developers) – Don Rhummy Jan 12 '12 at 00:11
  • @DonRhummy - Threads are a huge source of complication and bugs for both frameworks and users of frameworks. To require a developer to know about threads just to use a simple timer is more complication than javascript wants to foist on the developer. Further, the DOM is not thread-safe so (like with webworkers - the one place threads do exist in JS), you can't do very many meaningful things from a JS thread without access to the DOM or host objects. I'm sure that over time, we will get more threaded abilities, but it will be done in a way that only advanced developers ever need to use it. – jfriend00 Jan 12 '12 at 00:25
  • @DonRhummy - as to whether a JS engine actually uses real OS threads internally or not, that's purely an implementation choice that matters not to the web developer. The implementor could if they want. But everything happening in those threads would all have to get synchronized and sequenced to the one running JS thread in the end so a FIFO queue tends to be the perfect mechanism for that synchronization and ordering. – jfriend00 Jan 12 '12 at 00:27