clearTimeout without ID

2020-03-25 00:59发布

问题:

Is there any way to clear setTimeout() if it doesn't have an explicit ID? The problem is I'm not allowed to change some code that already ran and set the timers without any handler.

Does JS set 'anonymous handlers' to them? Are these timers stored anywhere accessible? Can I get any of those properties (the function the timer is about to call? the time it'll be called?)

回答1:

Nope, you can't without a reference. You could try something REALLY hacky (don't do this! it's just an illustration of hackyness) to clear all timeouts:

for(var i=0; i<100000; i++) clearTimeout(i);

but again that's not foolproof and well beyond hacky.

Solution? Fight be able to change the source, so you can do this properly - or see if you can override the function creating the timer.



回答2:

No. The clearTimeout method requires that the ID returned from setTimeout be provided in order to remove the timeout.

Could you post some more information about your scenario? Perhaps some code snippets? There may be a way to work around the scenario.



回答3:

Another possible hacky approach is to throw an error from somewhere within the timeout. For this to work, the error must (a) not be caught within a try-catch block; and (b) occur before the timeout has had a chance to take the actions you dislike. Depending on the content of the timeout this may be easy, hard, or impossible.

For example, if the timeout is registered like this:

setTimeout(function(){
   if(document.URL.toUpperCase() === "..."){
      // do something that you don't like
   }
}, 60000);

then the only way (I think) that you can throw an error is to monkey-patch the function String.prototype.toUpperCase, and check whether the calling function is the offending timeout. You can't make this check with absolute certainty, but (new Error).stack will certainly come in handy...you can compare against the expected stack trace. You can do similar things by monkey patching property getters, or perhaps by setting a specific object to undefined. ES6 might give some additional possibilities.

This is decidedly hacky, and it doesn't actually clear the timeout, it only prevents it from having any outwardly observable behavior. However, it may just do the trick! (If performance is relevant, then be careful with your monkey-patching.)



回答4:

No. But you could make the handler check whether it should still handle the event (with a boolean variable).