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. :)
Related
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++;
}
I'm trying to run an asynchronous for loop, which runs a synchronous function and then waits for a period of time. My code is :
function loopExec (i,imax, execFunc,param1) {
execFunc(i,param1);//Launch synchronous function which takes some time
var y=i+1;
if (y < imax) { // if the counter < imax, call the loop function
setTimeout(function () { // call a 0.1s setTimeout when the loop is called
loopExec(y,imax, execFunc,param1); // .. again which will trigger another call
}, 100);
}
else if(y==imax){
anotherFunction(param1);// The loop is over, clean up and log
}
}
The behaviour that I want is :
execFunc(1) -> wait 100ms -> execFunc2-> wait...
A bit like this
The behaviour that I have is execFunc1, execFunc2, etc all launching at 100 ms interval, without waiting for completion of the previous one, resulting in a read/write conflict as these functions interact with files.
I don't know if this has anything to do with it, but I'm using electron/nodeJS.
T.J. Crowder was right, the error is not in this function, but in the function it was calling.
This code does what is expected.
If you want to do something like this
this code will works.
var i = 0;
var imax = 10;
function myFunction() {
console.log('balbla', i);
i+=1;
if(i !== imax) setTimeout(myFunction, 100);
}
setTimeout(myFunction, 100);
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')
}
Sorry if this question has already been asked here before, I could not find a suitable answer.
I am wanting to create a JavaScript sleep/delay/wait function that I can call anywhere in the script, like jQuery's .delay()
I am not able to use setTimeout, as I have a script that is generated by php, and so am not able to put it into two different functions, with the timeout in the middle. I need to create a function that allows me to do
alert("time started");
sleep(4000);
alert("time up");
I really do not want to use jQuery.
Here's a solution using the new async/await syntax.
async function testWait() {
alert('going to wait for 5 second');
await wait(5000);
alert('finally wait is over');
}
function wait(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
Note: You can call function wait only in async functions
You cannot just put in a function to pause Javascript unfortunately.
You have to use setTimeout()
Example:
function startTimer () {
timer.start();
setTimeout(stopTimer,5000);
}
function stopTimer () {
timer.stop();
}
EDIT:
For your user generated countdown, it is just as simple.
HTML:
<input type="number" id="delay" min="1" max="5">
JS:
var delayInSeconds = parseInt(delay.value);
var delayInMilliseconds = delayInSeconds*1000;
function startTimer () {
timer.start();
setTimeout(stopTimer,delayInMilliseconds);
}
function stopTimer () {
timer.stop;
}
Now you simply need to add a trigger for startTimer(), such as onchange.
You will have to use a setTimeout so I see your issue as
I have a script that is generated by PHP, and so am not able to put it into two different functions
What prevents you from generating two functions in your script?
function fizz() {
var a;
a = 'buzz';
// sleep x desired
a = 'complete';
}
Could be rewritten as
function foo() {
var a; // variable raised so shared across functions below
function bar() { // consider this to be start of fizz
a = 'buzz';
setTimeout(baz, x); // start wait
} // code split here for timeout break
function baz() { // after wait
a = 'complete';
} // end of fizz
bar(); // start it
}
You'll notice that a inside baz starts as buzz when it is invoked and at the end of invocation, a inside foo will be "complete".
Basically, wrap everything in a function, move all variables up into that wrapping function such that the contained functions inherit them. Then, every time you encounter wait NUMBER seconds you echo a setTimeout, end the function and start a new function to pick up where you left off.
The behavior exact to the one specified by you is impossible in JS as implemented in current browsers. Sorry.
Well, you could in theory make a function with a loop where loop's end condition would be based on time, but this would hog your CPU, make browser unresponsive and would be extremely poor design. I refuse to even write an example for this ;)
Update: My answer got -1'd (unfairly), but I guess I could mention that in ES6 (which is not implemented in browsers yet, nor is it enabled in Node.js by default), it will be possible to write a asynchronous code in a synchronous fashion. You would need promises and generators for that.
You can use it today, for instance in Node.js with harmony flags, using Q.spawn(), see this blog post for example (last example there).
You can use this -
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
You could use the following code, it does a recursive call into the function in order to properly wait for the desired time.
function exportar(page,miliseconds,totalpages)
{
if (page <= totalpages)
{
nextpage = page + 1;
console.log('fnExcelReport('+ page +'); nextpage = '+ nextpage + '; miliseconds = '+ miliseconds + '; totalpages = '+ totalpages );
fnExcelReport(page);
setTimeout(function(){
exportar(nextpage,miliseconds,totalpages);
},miliseconds);
};
}
I have a strange issue on the project I'm working with. This changes an image source and a content of a div automatically.
I have coded a function, but it falls into infinite loop and page does not load (page is showing the loading page always).
These are the codes:
$.fn.extend({
changehaber: function(a){
$('#cokokunanlarcontent').fadeOut('slow',function() {
$('.jquerycokokunanlarbutton').attr('src','images/sabah/buton-pasif.png');
$('img[rel="'+a+'"]').attr('src','images/sabah/buton-aktif.png');
}).html($('#'+a).html()).fadeIn('slow');
return this;
}
});
function slidecokokunanlar() {
$('#cokokunanlarcontent').html($('#cokokunanlar1').html()).delay(3000).changehaber('cokokunanlar2').delay(3000).changehaber('cokokunanlar3').delay(3000).changehaber('cokokunanlar4').delay(3000).changehaber('cokokunanlar5').delay(3000);
slidecokokunanlar();
}
slidecokokunanlar();
What's the issue here, when this is executed, I want the function to work infinitely, but the page shows it's always loading. This is the console's output:
Uncaught RangeError: Maximum call stack size exceeded
Thanks in advance
You can't call a function from inside itself without blocking up the whole execution stack. By calling the function from inside itself, you're effectively preventing it from ever returning, and as Javascript is single-threaded, everything will grind to a halt!
Change your function to this:
function slidecokokunanlar() {
$('#cokokunanlarcontent').html($('#cokokunanlar1').html()).delay(3000)...
setTimeout(slidecokokunanlar, 0);
}
This allows for concurrent execution without blocking the UI, thus allowing your page to remain responsive.
See this article on "chunking" for more information on how this works.
This is because JavaScript doesn't have proper tail calls.
Your function calls itself at the end of itself forever. The first one never finishes and returns, nor does the second, nor do any of them until you run out of stack and explode.
You might try using setTimeout instead. See an example on jsFiddle.
EDIT You might not want to use 0 unless you really need it to be running continuously. Even using 100, you'd execute the function 10 times per second.
function foo(){
console.log('foo');
setTimeout(foo, 0);
}
foo();
Here's a cleaner way to do it.
var coko = $('#cokokunanlarcontent'); // cokokunanlarcontent
var cokos = $('[id^="cokokunanlar"]').not(coko); // cokokunanlar1..2..3 etc
var total = cokos.length; // total quantity
var i = 0;
var allow = true;
$('.jquerycokokunanlarbutton').attr('src','images/sabah/buton-pasif.png');
function slidecokokunanlar( isRestart ) {
if( !isRestart ) {
$('img[rel="' + cokos[i].id + '"]').attr('src','images/sabah/buton-aktif.png');
coko.html( cokos.eq(i).html() )
.fadeIn( 'slow' );
}
if( allow ) {
coko.delay( 3000 )
.fadeOut('slow', function() {
i = (++i % total);
slidecokokunanlar(); // recursively call with next index or 0
});
}
}
slidecokokunanlar(); // start it off
function restartSlider() {
allow = true;
slidecokokunanlar( true );
}
function stopSlider() {
allow = false;
}
stopSlider(); // to stop it
restartSlider(); // to restart it