Perform early execution

I use debouncing to execute events after a timeout using setimeout. The problem I have is that other javascript events expect these events to happen synchronously. Since they execute after a timeout, I would like them to be able to fire them prematurely due to other javascript events (so these events requiring them do not crash).

Anywhom if I do something like:

timeout = setTimeout(function() { alert('hi'); }, 10000); 

and I want this to happen up to 10 seconds, how can I do this?

If necessary, the solution may include jquery. Thanks!

Edit: Is it possible to do this with simple access to a timeout object?

+6
source share
5 answers

So, if you do something that delays your own function:

 function sayHi() { alert('hi'); } 

You can use timeout and regular function call:

 var timeout = setTimeout(sayHi, 10000); // say hi after 10 seconds 

To call it before the timeout expires, just call the function when you need:

 sayHi(); 

Am I on the right track here? If you need to cancel the timeout, call clearTimeout() in your timeout variable.

 if (timeout) clearTimeout(timeout); 
+6
source

You cannot track it with the standard setTimeout , but Javascript allows you to enhance features as you see fit.

For example, you may have your own extended setTimeout :

 var _setTimeout = window.setTimeout; var timeouts = []; window.setTimeout = function(fn, ms) { var id = _setTimeout(fn, ms); timeouts[id] = fn; return id; }; window.premature = function(id) { var fn = timeouts[id]; if (fn) { clearTimeout(id); if (fn instanceof String) { eval(fn); } else { fn() } } }; function printDate(str) { $("body").append("<p>" + str + ". " + new Date() + "</p>"); } $(function() { var id1 = setTimeout(function() { printDate("id1"); }, 10000); var id2 = setTimeout(function() { printDate("id2"); }, 10000); printDate("first one"); // just to demonstrate that the string version works too setTimeout("window.premature(" + id1 +")", 5000); }); 

You can see it in action on jsFiddle

Please note that this simple hack does not account for clearing used identifiers when timeouts do occur, but it just means that you can do such things in Javascript if you really need to.

+6
source

polyfill solution

Here is some javascript that I updated from a previous project, now it has been expanded using trigger and update methods; it is similar to John Wickholm's solution (+1) - but a bit more complete, given clearing, passing arguments, and preventing eval if necessary:

 (function(keep){ /// a few things to remember keep.setTimeout = window.setTimeout; keep.clearTimeout = window.clearTimeout; keep.TO = function(){}; keep.list = {}; keep.settings = { eval: false /// set this to true if you wish to support string timeouts }; /** * Quick check function to prevent eval */ keep.checkParam = function( param ){ if ( !keep.settings.eval && typeof param == 'string' ) { throw new Error('setTimeout blocked evaluation of string, ' + 'use a function instead.'); return false; } else if ( param ) { return true; } }; /** * Simple function constructor to avoid trapping unwanted references */ keep.makeFunction = function(data){ return function(args){ /// copy our args array args = data.args.slice(); /// do we allow eval? if ( keep.settings.eval ) { /// if so, reuse setTimeout for it abilities args[0] = data.param; /// use the original param args[1] = 0; /// trigger immediately keep.setTimeout.apply( window, args ); } // more secure, assume dealing with function -- not string else if ( keep.checkParam( data.param ) && data.param.apply ) { data.param.apply( window, args.slice(2) ); } else { throw new Error('unsupported param for setTimeout' + ' ie non-function used.'); } /// clear our storage of this tid window.clearTimeout( data.tid ); }; }; /** * Sets timeouts just like you would expect */ window.setTimeout = function( param, timeout ){ if ( keep.checkParam( param ) ) { var tid, data; /// support passing a timeout object as param if ( param instanceof keep.TO ) { data = param; data.args[1] = data.timeout; } else { /// create an object to store the timeout info data = new keep.TO(); data.func = keep.makeFunction(data); data.param = param; data.timeout = timeout; data.args = Array.prototype.slice.call(arguments,0); data.args[0] = data.func; } data.tid = keep.setTimeout.apply( window, data.args ); keep.list[data.tid] = data; /// enhance the returned number to support .clear, .trigger and .update tid = new Number(data.tid); tid.clear = window.clearTimeout; tid.trigger = window.triggerTimeout; tid.update = window.updateTimeout; return tid; } }; /** * Clearing timeouts since 2013 */ window.clearTimeout = function( tid ){ if ( this instanceof Number ) { tid = 0 + this; } var obj; if ( (obj = window.getTimeout(tid)) ) { delete keep.list[tid]; keep.clearTimeout.call(window, tid); } }; /** * Returns the internal timeout storage object */ window.getTimeout = function( tid ){ var obj; if ( (obj = keep.list[tid]) ) { return obj; } }; /** * Clears and fires a timeout before it outed time */ window.triggerTimeout = function( tid ){ if ( this instanceof Number ) { tid = 0 + this; } var obj; if ( (obj = window.getTimeout(tid)) ) { window.clearTimeout(tid); obj.func.call(window); } else { throw new Error('No Timeout found to trigger for ID '+ tid); } }; /** * Clears and recreates an existing timeout, returns a new timeout id. */ window.updateTimeout = function( tid, timeout ){ if ( this instanceof Number ) { if ( arguments.length == 1 ) { timeout = tid; } tid = 0 + this; } var obj; if ( (obj = window.getTimeout(tid)) ) { obj.timeout = timeout; window.clearTimeout(tid); return window.setTimeout(obj); } else { throw new Error('No Timeout found to update for ID ' + tid); } }; /** * Utility function to tidy up */ window.clearAllTimeouts = function(){ for ( var i in keep.list ) { window.clearTimeout(i); }; }; /// Tidy up window.onunload = (function(previous){ return function(){ window.clearAllTimeouts(); keep.list = {}; previous && previous.call(window); }; }(window.onunload)); })({}); 

turn on

Just put the above in js file and include it on your page using a regular script tag, the code does not need to be called in any way:

 <script src="timeouts.js"></script> 

Using

Obviously, this should be used as a regular setTimeout call, but now you have additional methods that should provide more flexibility.

 var tid = setTimeout( function(){ alert('OK Computer') }, 2000 ); 

For example, you can cancel the original and force the timeout to start earlier:

 setTimeout( function(){ triggerTimeout( tid ); }, 500 ); 

Or you can update the timeout (make sure we remember the new returned tid):

 setTimeout( function(){ tid = updateTimeout( tid, 5000 ); }, 500 ); 

You can also do the usual:

 setTimeout( function(){ clearTimeout( tid ); }, 1000 ); 

Each of these methods is also available through tid itself:

 setTimeout( function(){ tid.trigger(); }, 1000 ); setTimeout( function(){ tid.update( 5000 ); }, 1000 ); setTimeout( function(){ tid.clear(); }, 1000 ); 

By default, this code prevents the use of setTimeout with the string parameter, mainly because it is a much better coding style for passing functions, not strings. To change this, you can switch the following setting to true:

 keep.settings = { eval: true }; 

However, this is not recommended.

There is also an additional advantage in order to exclude eval due to the fact that the code will use a normal function call to trigger a timeout, i.e. .apply() . This means that any browser you use, you can pass arguments to the timeout function through setTimeout - which is usually not something that you can rely on cross-browser. eg:

 setTimeout( function(a){ alert(a) }, 2000, 'Hello World' ); 
+4
source

Just pull out the function and give it a name:

 function handler(){ alert('hi'); } timeout = setTimeout(handler, 10000); 

then you can call it in other places with handler();

+1
source

Use clearTimeout and reschedule.

0
source

Source: https://habr.com/ru/post/909249/


All Articles