var clearId:int = setTimeout(function():void{
//some code here
clearTimeout(clearId);
},2000);
Is this valid AS3? Anyone see problems with it?
Whilst this compiles without warnings or errors, and is valid AS3, there is un-needed code.
The setTimeout function only runs a function once.
The setInterval function on the other hand runs a function at a specified interval until clearInterval is called.
clearTimeout is used to stop a timeout event that has been set occuring.
Because the timeout only occurs once, there is no need to clear it in the timeout function.
If you were using setInterval, then you would need to clearInterval when you no longer wanted the function to be called.
Is it valid? Yes.
Does it work? Yes.
Does it make any sense? No.
A timeout only executes once. The closure necessarily is only called after the timeout has already completed. Now, if you were using an interval, it would make sense.
The method works because the compiler defines all of those local variables up front, making them automatically accessible. Basically, it does something like this:
var clearId:int;
clearId = setInterval(function():void
{
clearInterval(clearId);
}, 2000);
Related
Let's say I have a function someFunction() that i don't any control of what inside of it.
I wish to run this function for no more than 5 seconds.
I've tried using a setTimeout or setInterval like this:
try {
const timeoutId = setTimeout(() => {
throw new Error("Time over");
}, 5000);
someFunction();
clearTimeout(timeoutId);
} catch (e) {
...
}
The problem in this is that if there is an infinite loop in someFunction() then the timeout will never get called.
what's the simplest way to solve this? I thought about using a worker thread but passing arguments to another thread is problematic in my case.
Thanks a lot!
what's the simplest way to solve this?
You can't, within the same execution environment. If you don't control what's inside the function, there's no way for you to stop it from your code. Once you've made the call to someFunction, your code doesn't get control back until that function has run to completion.¹ If it loops infinitely, it loops infinitely.
You could spawn a worker thread or child process that runs the function in a separate environment, which you can then terminate (1, 2) after a period of time. But within your main environment, you can't do it.
¹ Note that in the case of an async function, "run(s) to completion" means "reaches the point where it returns its promise" (the first await, return [implicit or explicit], or uncaught error). So in theory if you had an async function that started something then didn't go into the finite loop until after the first await (say), your code would get an opportunity to run, but if you have no control over the function's code there's nothing you can do from keeping it from continuing again (other than run an infinite loop of your own, which of course you wouldn't want to do).
I would like to put a delay after a button is pressed in order for the button to load the data from the cache before executing the next line of code. Would putting a sleep be the best way to do this?
Something like this or is there an alternative approach to best solve this problem?
setInterval(document.getElementById("generateButton"), 1000);
Don't use setInterval to do this. It doesn't have the functionality you seem to desire (it repeats). Instead, use jQuery and do something like this:
$("#generateButton").click(function(event){
setTimeout(function(){
//Do what the button normally does
}, 1000);
});
Or (without JQuery):
var generateButton = document.getElementById("generateButton");
generateButton.addEventListener("click", function(){
setTimeout(function(){
//Do what the button normally does
}, 1000);
});
Using setTimeout over setInterval is preferred in your case because setTimeout runs only once while setInterval runs multiple times.
I assume you have, in your html, <button id='generateButton' onclick='someFunction()'>Button Text</button>. Remove the onclick='someFunction() and put your someFunction() where I said (in the examples) "Do what the button normally does."
You can also add in the code that loads the cache a method that calls another method once the cache has been loaded (when the someFunction() from the button is called, it loads the cache, and at the end of the function (set this up using callbacks), once the cache has been loaded, it calls another method onCacheLoaded() that can be run once the cache has been loaded.
You should use callbacks, so the moment you loaded data from cache you can call it and continue executing the rest of the script.
You cannot use interval since you cannot be sure how much time is needed for the data to load. Though keep in mind the asynchronous nature of javascript and don't block the part of the script that does not depend on the data that's being loaded.
Try setTimeout:
myButton.addEventListener('click', function() {
setTimeout(delayed, 1e3); // Delay code
}, false);
function delayed() {
// Do whatever
}
Note setInterval runs a function periodically, setTimeout only once.
Also note that the delayed code must be a function (or a string which will be evaluated, but better avoid that). However, document.getElementById("generateButton") returns an html element (or null).
If i give an ID to a JavaScript setTimeout function, how do I then execute or trigger it?
var timerId = setTimeout(function(){alert('doh')}, 1000);
//timerId; doesn't work,
//trigger it here
clearTimeout(timerId)
The action of calling the setTimeout() should execute it. I believe what you are trying to do is have this action repeat itself every second. For that you'll need to use setInterval() instead:
var timerId = setInterval(function(){alert('doh')}, 1000);
// you'll get an alert every second untill clearTimeout(timerId) is called.
As #j08691 says, you probably don't see the alert because you're calling clearTimeout() immediatly after you call setTimeout().
As a side note, you probably don't want to use the alert() function to debug this as alerts are a blocking action - no other JS will be executed while the alert is being displayed. You'll be much better off using console.log() to for this type of debugging. It's not blocking and will allow you very easily to inspect your variables.
The only use the return value of setTimeout has is to cancel the timer, which you are already doing with clearTimeout.
If you want to trigger it early, then you should clear it and then call the original function.
For example:
function doh(){
alert('doh')
}
var timerId = setTimeout(doh, 1000);
clearTimeout(timerId)
doh();
I am not quite sure what the technical term for this is. I have a GUI with interactive graphics. After the user has interacted with the GUI, I need to perform some CPU intensive action. However, user input is very frequent, so I only want to call the function after e.g. 1000ms of no userinput. Below the pattern that I use:
scheduler = (function(){
var timer;
function exec(call, delay){
clearTimeout(timer);
timer = setTimeout(call, delay);
};
return exec;
})()
I.e. if the 3 calls to scheduler are done right after each other, only the final one will actually be executed:
scheduler(function(){alert('foo')}, 1000);
scheduler(function(){alert('bar')}, 1000);
scheduler(function(){alert('zoo')}, 1000);
It seems to work, but it feels a bit hacky I am a little worried about any caveats of Javascript setTimeout, especially the scoping problems. Does this seem like a reliable pattern I could use on a larger scale? Will the inline function that I pass to scheduler be able to lookup all objects in its lexical scope as usual, when it is called by settimeout? What about if I have several of these scheduler instances? Could they interfere with each other? Is there an alternative way of accomplishing this?
You could opt for using web worker threads instead:
https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers
http://www.html5rocks.com/en/tutorials/workers/basics/
What I would do:
http://jsfiddle.net/gunderson/4XXQ4/1/
var severQueue = [];
var delay;
$("#inputSquare").mousemove(onMouseMove);
function onMouseMove(){
if (delay){
clearTimeout(delay);
}
serverQueue.push("doSomething")
delay = setTimeout(sendToServer, 1000);
}
function sendToServer(){
console.log(serverQueue.length);
delay = null;
$("#inputSquare").addClass("activated");
// do some ajax using serverQueue
// we'll just simulate it with another timeout
for (var i in serverQueue){
serverQueue.pop();
}
onComplete = setTimeout(onAjaxComplete, 1000);
}
function onAjaxComplete(){
$("#inputSquare").removeClass("activated");
}
In theory, your solution looks like it will work. There are no scoping problems related to you passing a callback function to your scheduler function; the callback will close over whatever environment it was created in, just like any other function in JavaScript. That being said, scoping rules can be a bit tricky in JavaScript, so make sure that you read up on it.
In practice, there may be some browser-specific issues related to setTimeout that may make this solution unworkable. For example, the frequency at which certain browsers execute setTimeout callbacks may vary such that you'll be waiting longer than you expect for a callback to be executed. All setTimeout callbacks will be executed sequentially; they'll never be executed in parallel. However, you have guarantees as to what order they will be executed in.
All that being said, any major gotcha in your solution will likely have more to do with the callbacks that your registering rather than the way in which you're registering them.
The debounce function in underscore.js does exactly this:
debounce _.debounce(function, wait, [immediate])
Creates and returns a new debounced version of the passed function that will postpone its execution until after wait milliseconds have
elapsed since the last time it was invoked. Useful for implementing
behavior that should only happen after the input has stopped arriving.
For example: rendering a preview of a Markdown comment, recalculating
a layout after the window has stopped being resized, and so on.
I have a piece of Javascript that checks for a condition (via an AJAX call) every n seconds. If that condition is true, it stops checking. I have implemented it in the following way:
var stopTimer;
var timerId = setInterval(function() {
/* Make Ajax Calls and set stopTimer */
if (stopTimer) {
clearInterval(timerId);
}
}, 10000);
However, I find erratic behaviour: Works sometimes, but at other times, it keeps checking forever. I have checked that (as much as is possible) there is no error in any part of the code.
I am therefore suspecting that calling clearInterval inside a setInterval handler might be the culprit. Is that right? Is it OK to call clearInterval inside a setInterval handler?
Thank you for your attention
It's safe. The issue is probably to do with stopTimer not being set as you expect.
I don't think there will be any issue with your code unless the AJAX function is erroneous. You have to take care of the success and error callbacks of the AJAX function so that there won't be any issue with the loop not being stopped.
Also I think you are constantly polling the server for a response and then doing the appropriate action. You can use Reverse AJAX to do this kind of process.
Make sure you're not inadvertently re-using the same timer name elsewhere in your code which would result in you always stopping the second timer to be defined.
Either give the timer a unique name, or scope it to a function
var timerForAjax = setInterval(function() {
/* Make Ajax Calls and set stopTimer */
if (stopTimer)
{
clearInterval(timerForAjax);
}
}, 10000);
I was careless enough to call my timer interval and didn't realize I was creating two timers in the same scope both called interval. Blamed iOS8 for about an hour until I realized that that was nothing to do with it.