Sometimes you’re in JS and you want to perform some task once something else returns (as is reasonable in an asynchronous world), but if you just fire off a bunch of intervals, you’ll eventually choke the browser. My solution is to add geometric timer falloff and a maximum timeout. this way the longer the task takes the less work we do as we wait, and at some point (in this example ~16 seconds) it gives up. This strategy has been working well for me.
| if(!Function.actionTimeout) Function.actionTimeout = 16384; | |
| if(!Function.whenTrue){ | |
| Function.implement({ | |
| whenTrue : function(actionFunction, args, delayFunction, timeoutFunction, timeout, counter){ | |
| if(!timeout) timeout = Function.actionTimeout; | |
| if(!counter) counter = 0; | |
| if(!timeoutFunction) timeoutFunction = function(event){ | |
| throw('Condition not met after '+event.time+'ms'); | |
| }; | |
| var result = this(); | |
| if(!result){ | |
| var delayTime = Math.pow(2, counter); // geometric falloff | |
| if(delayTime >= timeout){ | |
| timeoutFunction({ | |
| count : counter, | |
| time : delayTime | |
| }); | |
| return; | |
| } | |
| counter++; | |
| this.whenTrue.delay(delayTime, this, [actionFunction, args, delayFunction, timeoutFunction, timeout, counter]); | |
| if(delayFunction) delayFunction({ | |
| count : counter, | |
| time : delayTime | |
| }); | |
| }else{ | |
| actionFunction.apply(this, args); | |
| } | |
| } | |
| }); | |
| } |
Then call it like:
| (function(){ | |
| //code here | |
| }).whenTrue(function(arg1){ | |
| //code here | |
| }, [val1]); |
or
| myFunction.whenTrue(function(arg1){ | |
| //code here | |
| }, [val1]); |
Enjoy,
-abbey