Force JavaScript setTimout function to run after x miliseconds - javascript

I am trying to make a timeout function that throws an error in case a function hangs for too long.
I have the following code:
function go() {
try{
console.log('started, timeout in 2 seconds...');
setTimeout(()=>{
throw new Error('Timed Out!');
}, 2000);
while(true){
//will run forever
}
}catch (e) {
console.log('timeout function worked!');
}
}
go();
However, the error is never thrown. I think this is because of how the event loop works in JS, but I'd like for my timeout function to execute after 2 seconds regardless of what else is happening. How do I achieve this?

I'd like for my timeout function to execute after 2 seconds regardless of what else is happening. How do I achieve this?
You can't really. As you suspected, the issue is related to the event loop. There's only one thread at your disposal, and you've put it into an infinite loop. Since you never return, the event loop doesn't have a chance to run the function specified by the setTimeout.
If you want your while loop to stop, your while loop needs to be the one to stop it. Perhaps something like this:
const before = Date.now();
while (true) {
// do stuff
if (Date.now() - before > 2000) {
throw new Error('Timed Out!');
}
}

I think this is because you enter inside the infinite loop first and never get out so your settimeout will never fire.
I don't know what your are try to achieve but if you want to throw error, move the while loop inside the settimeout at the end.
By the way that make no sense

setTimeout() doesnot work as you think. Until the while loop is running. The setTimeout() function will not be called.
Javascript doesnot support multithreading because it is an interpreted language.
Multithreading: is a type of execution model that allows multiple threads to exist.See more
Below is the example.
function loop(){
console.time('time');
for(let i = 0;i<10000000;i++){
if(i % 2000000 === 0) console.log("I am looping");
}
console.timeEnd('time');
console.log("Loop finished");
}
loop();
setTimeout(() => {
console.log("I am logged from setTimeout")
},0)

You can't do anything if the event loop can't proceed. But, the below code should be closer to what you are looking for. If you need to do a while statement, do the code further down.
function go() {
try{
var timeout = setTimeout(()=>{
throw new Error('Timed Out!');
}, 2000);
//do stuff; it can't hog the event loop
}catch(e){
}
clearTimeout(timeout);
return true; //return value
}
go();
var iterations = 0;
while(condition && iterations < 10){
//do stuff
iterations++;
}

Related

Why does the while loop keeps looping even when the object reference value changed and the break statement should execute?

after executing the command sw.start(), when I run sw.stop() which would change the value to running.value = false and the break statement should execute cause the running.value is false but that doesn't happen...
It isn't exactly a Stopwatch, rather stop calculating program gone wrong, :)
some weird things that happen when I run this script in the console:
when I run sw.stop(), it works
when I run sw.resetit(), it works
sw.duration() also works
when I run sw.start() maybe it starts the calculations
but after that when run any other commands the console doesn't take any input or respond, I have to pause the script from running from the source dev tools and then it shows the output of other commands if I had entered any after it stopped responding. But after entering sw.start(), the console doesn't respond.
Anyways, is there any way, by which I could write another method, that somehow stops the start() method.
In other words could I write a function and then call it from a method to start and then stop it from another method.
function StopWatch(){
let current = {t:0};
let running = {value:false};
//this function doesn't stop somehow
const timmy = () => {while(true){
current.t += 0.01;
if(running.value===false){
//this block never runs??
console.log(`stopping...`);
break;
}
};
}
this.start = function(){
if(running.value === true){
throw new Error('It is already running');
} else {
running.value = true;
//timer will go here
timmy();
}
}
//stop doesn't seem to work
this.stop = function(){
if(running.value === false){
throw new Error(`It's is not running.`);
}
else {
running.value = false;
console.log(running.value);
//i hope this works
//
}
}
this.resetit = function(){
if(current.t === 0){
throw new Error(`It's all ready reset`);
}
else{
current.t = 0;
}
}
this.duration = function() {
return `${current.t}s`;
}
}
const sw = new StopWatch();
some questions you don't have to answer:
could I write a function and then call it from a method to start and then stop it from another method.
How to stop a function which loops by calling another function, which changes the value of an object or variable, which if set to 'false' will then stop the function that loops because the function is looping on the object or variables value which is true or false? it is even possible??
This is causing the problem:
const timmy = () => {
while(true){ // --> never stops
current.t += 0.01;
if(running.value===false){
//this block never runs??
console.log(`stopping...`);
break;
}
};
}
run the loop while running.value is true:
const timmy = () => {
while(running.value){
current.t += 0.01;
};
}
While loop always executes the code at least once.
So when you run StopWatch(); for first-time it will not execute correctly
if you try it running stopwatch(); twice it will be working.
So coming to the point,
we have to use
If-Condition within the while loop
so it will check the condition and
executes in the correct direction.

Why does this javascript sleep function skip immediately?

Where isPaused becomes true, the sleep function should go into an infinite loop right??? but for some reason it does not, instead it will print "here2" immediately after? i am using this with an async function which when it is done the bool isPaused becomes false again.
var isPaused = false;
function sleep() {
if (isPaused == true) {
setTimeout(function(){sleep()},1000);
}
};
console.log("here");
isPaused = true;
sleep();
console.log("here 2");
how can i fix it so it will wait, instead of continuing.
If you want to wait for the timer, you need to use a Promise with async and await:
(async () => {
var isPaused = false;
setTimeout(function() {
isPaused = false;
}, 3000);
async function sleep() {
if (isPaused == true) {
await new Promise(resolve => {
setTimeout(async function() {
await sleep();
resolve()
}, 1000);
});
}
return;
}
console.log("here");
isPaused = true;
await sleep();
console.log("here 2");
})();
Here is a JSFiddle.
Your code will run the sleep function, then run it again after 1000 milliseconds.
What your code does:
Set isPaused to false
Define the sleep function (not execute it)
log "here"
Set isPaused to true
Execute the sleep function, it will be called again after 1000ms, but the program doesn't wait for this, so it already executes the next line.
log "here 2"
Because the function sleep is done setting the timeout, so the code can then continue the rest of the operations.
Then after having continued operations for 1s (1000ms) it will perform another sleep, after which it is free to run any other potentially remaining operations.
So the infinite loop does happen, it just doesn't prohibit other code from running.
Try putting a console.log('test') in the first line of the sleep function.
function sleep() {
console.log("test")
if (isPaused == true) {
setTimeout(function(){
sleep()
},1000);
}
};
A little too much to get into here, and others can explain a lot better than me, but look into the JS Event Loop, that should clarify some things!
That's already an infinite loop. Just try to add an "console.log('loop')" inside the setTimeout function and you will see how it's called each second.
Also, remember javascript is not syncronous, so it will print here 2 before the sleep (remember, it requires 1 sec), but it keep working in the infinite loop

How can I stop my Javascript code once an event handler has been clicked?

So my hmtl eventhandeling button is
<input type="button" value="Stop" onclick="stop()">
and the javascript function stop() is:
function stop()
{
stop.called = true;
}
and I call this function here:
....
var interval = setInterval(function ()
{
// call generation again for each generation, passing in the previous generations best offspring
best_offspring = generation(best_offspring, characters, amount_offspring, mutation_rate, target_text);
document.getElementById("output_text").value = best_offspring;
document.getElementById("generations").value = generations;
if (score_met)
{
clearInterval(interval);
}
}, delay);
if (stop.called)
{
return;
}
// so that we know that the program has been run atleast once
start = true;
}
Do you need more of the code?
Anyway, what I want is to stop the execution when the function is called. But my interval loop continues even though the stop() function is called. I have also tried to put the ´if(stop.called)insidevar interval` loop. But that didnt work either.
Any ideas? Do I need to provide more info?
if (stop.called)
{
clearInterval(interval);
}
¿?
var interval = setInterval(function ()
{
// call generation again for each generation, passing in the previous generations best offspring
best_offspring = generation(best_offspring, characters, amount_offspring, mutation_rate, target_text);
document.getElementById("output_text").value = best_offspring;
document.getElementById("generations").value = generations;
if (score_met || stop.called)
{
clearInterval(interval);
}
}, delay);
if (stop.called)
{
clearInterval(interval);
return;
}
// so that we know that the program has been run atleast once
start = true;
}
SetInterval returns an Id so you can simply call clearInterval(id);. Return break etc. Doesnt work because it is not really a loop like for and while.

Creating a "delay" function in JS?

I've been reading about setTimeout and other such timers. But I'm wondering if it's possible to work up a custom function so that all you would need to do is something like this:
//code
delay(time);
//more code
Is this possible?
UPDATE: Ok, I kind of get it. So if that isn't reasonably possible, how would you go about delaying a loop AFTER the first time. I want it to run immediately upon execution but they delay on each iteration afterward.
New UPDATE: I figure since my initial thought fell through, it might just be easier to show you the code I have.
function autoFarm (clickEvent){
var farmTargets = [
"6_300_1",
"6_300_3",
"6_300_4",
"6_300_5",
"6_300_7"];
setTimeout(function() {
$.each (farmTargets, function(index, target){
var extraData = '{"end_pos":"' + target + '","purpose":0,"upshift":1,"bring_res":{"0":0,"2":0,"1":0},"bring_ship":{"1":25,"11":0},"rate":100,"start_pos":"6_300_2"}';
var finalData = baseDataDora + extraData + "&type=1";
setTimeout(function(){
for (i = 0; i < farmTargets.length; i++){
postRequest(sendFleetURL + getSign(extraData). finalData, function(json){
});
}
}, 15000);
});//End each loop
}, 1320000);
}//End autoFarm
Basically, it should execute immediately and run the for loop 5 times on the first array element 15 seconds apart. Then 22 minutes later move to the next set and repeat for the entire array.
You can achieve something along those lines with generators. The idea is that continuation passing style (callback hell) can be flattened. The generator uses the yield keyword to pause the function, until the callback resumes it by calling its next method:
var async = function(gen) {
var g = gen()
function next(x) {
var cur = g.next(x)
if (cur.done) {
return cur.value
}
cur.value(next)
}
next()
}
var delay = function(time) {
return function(f) {
setTimeout(f, time)
}
}
async(function* () {
console.log('before')
yield delay(1000) // waits one second
console.log('middle')
yield delay(1000) // waits one second
console.log('after')
})
In CPS it would read something like:
console.log('before')
setTimeout(function() {
console.log('middle')
setTimeout(function() {
console.log('after')
}, 1000)
}, 1000)
This works in Chrome, Firefox and iojs today.
This isn't possible because of the way single-threaded event loops work. If this function were to exist, it would cause the entire UI thread to freeze until the delay was satisfied. setTimeout(cb, delay) is the nearest facility which schedules a function to be executed no earlier than the delay and at the end of the current event loop tick.
Update: Before somebody calls me on it, yes, you can theoretically engineer a delay function that freezes everything in place for a set amount of time. However, there is no reasonable excuse to do it this way.
To your second question:
function hello() {
console.log('hello');
}
// execute immediately
hello();
// then every 5 seconds
setInterval(hello, 5000);
As-written, no that's not possible.
If, instead you were to use a queue, delays in that manner are trivial.
jQuery's .queue() and .delay() functions are a good example of how this works, so I will use them as an example, however the general point stands for any queueing library.
Instead of:
//code
delay(time)
//more code
With a queue, you'd write:
$('...') //some selector to act on for jQuery
.queue(function (next) {
//code
//Indicate that the queued call is finished.
next();
//This allows async code to be executed in the queue,
//such as ajax and animations
})
.delay(time)
.queue(function (next) {
//more code
next();
});
Now, even if you ignore the lines used for comments, you can tell that there's a bit more boilerplate to achieve the desired behavior. I don't feel that it's excessive, because I find it relatively easy to read:
queue something to happen
wait for some number of milliseconds
queue something else to happen
Using a Promise, calling it inside an asynchronous function.
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const any_function = async() => {
await delay(2000);
console.log('this log has been delayed 2 secs')
}

Wait for few seconds before next action - Javascript

As commented in the code , I need a wait before checking the else if after writeFile(lFileData);. How to achieve this?
for(var i=0;i<mLocalStorageCount;i++)
{
if(i <= 1)
{
writeFile(lFileData); //This action takes a lot of time with its call backs. I need a wait here.
}
else if(i > 1 && i <=3)
{
someOtherfun()
}
You can use set interval in elseif function
setTimeout(function,3000);
You may want to rewrite the code to have the portion you want to run on a delay in its own function. From there call that function by calling performFunctionXAfterDelay() :
function performFunctionXAfterDelay() {
// 1000 ms delay
window.setTimeout(functionX,1000)
}
function functionX() {
// YOUR TIME DELAYED CODE
}
So that means the writeFile function is asynchronous?
I would create a callback function in the writeFile function itself and then do the someOtherfun().
Edit:
Due to you can not really do the rest of the iteration in the callback function (which you just said) you can do something like this:
function writeFile () {
... here goes your function ...
if ( finished ) {
window.finished = true;
}
}
for (yourForCondition) {
if () {
window.finished = false;
writeFile();
while (!window.finished) {}
}
if () {
someOtherFun();
}
}
It's a bit dirty, but it should work. It would loop until writeFile() says he is done.
Edit2:
Will probably not work since "while (!window.finished) {} is a busy-wait loop that will peg one core to 100% and probably make the browser ask the user if the script should be killed. – Frédéric Hamidi "
var t = setInterval("javascript expression", milliseconds);
clearInterval(t);
u can use setInterval
hi i think there is no need of wait before execution of "else if(i > 1 && i <=3)" code. because if "if(i <= 1)" condition is true and " writeFile(lFileData); " gets executed, control will no be given for "else" part and " someOtherfun()" will not get executed. :)

Categories

Resources