I want my program to check to see if something loaded every 500 milliseconds until it finds it. waitForSelector doesn't work (don't ask; it just doesn't). However, casper.exists("css3path") does find it.
Here's my code, I don't know if I'm just making some stupid mistake on a really basic level that I'm not seeing, or whether for loops don't work, or what the problem is.
casper.then(function(){
for(int i = 0; i < 100; i++){
if(casper.exists('#bookmark-FSE')){
i = 100;
} else{
casper.wait(500)
this.echo(i + 'seconds')
};
};
});
casper.then(function(){
//rest of my code
I know the error is in here, because if I replace the whole thing with a dumb wait(time, function(){ it works. The problem is that the time it takes varies greatly (3->6 seconds) and I'd like to cut it shorter. When I try to run it I get a syntax error message. Just for reference, I'm using phantomjs version 1.9.2. What am I doing wrong, is there any other way to do it (no waitFors are working)?
You cannot use any loop to wait for something in JavaScript. Since JavaScript has no blocking sleep() function or something like that, it is not possible to check for some condition and wait in a loop.
All then* and wait* functions are asynchronous step functions in CasperJS. It means that by calling then, the matching step is only scheduled in CasperJS's asynchronous environment.
You can recreate waitFor() easily with CasperJS like this:
casper.myWaitFor = function(test, then, onTimeout, timeout){
timeout = timeout || this.options.waitTimeout; // 5000
return this.then(function(){
if (test.call(this)) {
if (then) {
then.call(this);
}
}
this.wait(500, function _then(){
if (timeout - 500 > 0) {
this.myWaitFor(test, then, onTimeout, timeout - 500);
} else if (onTimeout) {
onTimeout.call(this);
} else {
throw new CasperError("Waited without success");
}
});
});
};
casper.myWaitForSelector = function(selector, then, onTimeout, timeout){
return this.myWaitFor(function(){
return this.exists(selector);
}, then, onTimeout, timeout)
};
Use it like this:
casper.start(url)
.then(function(){ /* do something */})
.myWaitForSelector('#bookmark-FSE', function(){
this.echo("success");
})
.run();
I doubt this will help you, but it's another implementation of waitFor().
You get a syntax error, because there is no int in JavaScript. You probably meant var.
I am trying to figure out why in my Code section, this.sleep(5000) seems to be getting called before my draw function, because it doesn't get drawn to the canvas until after sleep is done. any insights on why this isn't working the way I want it to?
Sleep function:
sleep: function(milliseconds) {
setTimeout(function(){
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds){
// Do nothing
}
},0);
},
Code:
var g = new Graph(this.diagram);
g.DrawPolygons(ctx,"blue");
this.sleep(5000);
Short answer
Don't do it this way. Even if you get it to work, it will be inconsistent, will cause you many problems, and is almost globally considered bad practice.
Long answer
JavaScript runtimes are almost always designed to be asynchronous. Your while loop is intended to make everything... wait. You cannot (or at least shouldn't) do that in most JavaScript environments.
Instead, schedule events/functions to be executed some number of ms in the future. This is what setTimeout is for. This removes the need for a sleep function.
Here's what your code might look like after the changes described above are applied:
var g = new Graph(this.diagram);
g.DrawPolygons(ctx, "blue");
setTimeout(function() {
g.DrawPolygons(ctx, "red"); // Or whatever
setTimeout(function() {
g.DrawPolygons(ctx, "yellow"); // Or whatever
// etc..
}, 5000);
}, 5000);
ES2015 update - using promises
To avoid potential deeply nested setTimeouts, you can use this
const sleep ms = new Promise(resolve => setTimeout(resolve,ms));
which is simply a promise that resolves in ms milliseconds. This allows you to keep everything in one block:
var g = new Graph(this.diagram);
g.DrawPolygons(ctx, "blue");
(async () => {
g.DrawPolygons(ctx, "red");
await sleep(5000);
g.DrawPolygons(ctx, "yellow");
await sleep(5000);
// ...
})()
Note two things:
Under the hood, there are still events/callback. It looks like C's or Python's sleep but behave very differently.
You can only use this inside asynchronous functions. See here for more information.
There are several problems with the code you've posted. First off, you should never use a while loop to halt code execution.
Secondly, you're setting a timeout, which allows other code to be executed in the interim (yes, even if the timeout is zero seconds). Remove that and you should be able to pause execution (BUT DON'T DO THIS):
sleep: function(milliseconds) {
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds){
// Do nothing
}
},
However, occupying the JS thread means that other browser operations (redraws, etc) will be halted until your sleep function exits. Just having this code in your JS file is an antipattern, you'd be better off finding a different way to solve your problem. Read up on the XY problem and ask a new question.
In case all you wanted to do was execute some code after a certain interval without blocking everything else, setTimeout is all you need.
sleep: function(ms, funcToExecute) {
setTimeout(funcToExecute, ms);
},
(Though at this point, sleep is redundant)
This is happening because of how JavaScript's setTimeout works. When you do:
setTimeout(function(){}, 0)
You are not actually telling it to run the function after 0ms (the lowest value is actually 4ms, but that's besides the point). You are telling it to run the function in the future. What it actually does is put the function at "the end of the stack". It'll finish running the function that called it, and maybe even run some UI redraws before it runs the timeout.
If this code is ran in a loop, your timeouts will not run at all when you think they will ;)
Also, remember JavaScript is single threaded. One thread runs your code as well as the UI redraws. Doing a while loop that does nothing and waits for 5 seconds will lock up the browser. It will prevent any user interaction and UI redraws. It might even make the OS think the browser crashed. DO NOT DO THIS!
Instead, try setting a timeout to run the next polygon after 5000ms:
var g = new Graph(this.diagram);
g.DrawPolygons(ctx,"blue");
setTimeout(function(){
// Code to run after the "sleep"
// Maybe another shape
g.DrawPolygons(ctx, "red");
}, 5000);
I'm making a little game, and i was making a character death sequence when I ran into this problem. The
eloop(setInterval(e_seq,100)
plays the ending sequence. After that, I want execution to stop for a second before displaying the score and stuff.
But the current sleep method i'm using pauses the entire execution, including the loop, while I want the loop to be completed before pausing the game for a second.
The place where sleep is called: (inside the main gameloop)
eloop=setInterval(e_seq,100);
sleep(1000);
The sleep method:
function sleep(msec)
{
var time= new Date().getTime();
while(time+msec>= new Date().getTime())
{}
}
any solutions?
PS: calling sleep at the end of the gameloop (inside an if condition checker) was pausing the execution before the gameloop began for some reason....
I think you probably want something more along the lines of
setTimeout(function () { e_seq(); }, 1000);
This would wait one second and then execute the e_seq() function, which I think is the purpose of your code, although it's open to a little interpretation...
Did you try just the setInterval?
setInterval(function(){ ... }, 3000);
i have tried something
var looper;
var looptime = 2000;
var doloop = function(){
console.log("doing this")
}
function begin(callthis){
looper = setInterval(callthis,looptime);
}
function pause(callthis,sleeptime){
clearInterval(looper);
setTimeout(function(){
looper = setInterval(callthis,looptime);
},sleeptime)
}
using like:
begin(doloop);
and pause with
pause(doloop,10000);
You need a callback when using "sleep" functionality. The sleep concept does not exist in JavaScript.
You should not use a busy-loop as you do as that will hold off any other processes as well as JavaScript is single threaded (incl. DOM updates). Use a timer instead but as timers are asynchronous you will have to use the mentioned callback.
It's not so complicated -
Modify the sleep method like this:
function sleep(timeout, callback) {
setTimout(callback, timeout); // or just call this directly...
}
(as you can see it's a bit excess with the wrapper so I would recommend just calling the setTimeout() directly).
Now you can implement your score screen into a function:
function showScores() {
...
}
Then when you want to delay a second before showing the score screen do:
sleep(1000, showScores);
or simply:
setTimeout(showScores, 1000);
Note that the rest of your code will continue after calling this method so make sure all code resides in functions so you can use them as callbacks.
I'm trying to return a variable only after it has been set within a setTimeout callback. I couldn't think of any other way to do this, but here's my attempt (I know the code seems silly, but it's to work around a Cordova bug). For reasons beyond my understanding, it results in an infinite loop.
function isConnected() {
var done = false;
setTimeout(function() {
done = true;
}, 500);
while (!done) {}
return navigator.connection.type!== Connection.NONE;
}
Can anyone explain to me why this is happening, or provide an alternative?
Update (solution):
function isConnected(callback) {
setTimeout(function() {
callback(navigator.connection.type !== Connection.NONE);
}, 500);
}
isConnected(function(connected) {
if (!connected)
alert('Not Connected');
});
You simply can't solve your problem that way. Because javascript is single threaded, the setTimeout callback can only run when your JS thread of execution finishes so with your infinite loop, it will never get to run and your code will hang. Eventually the browser will complain about a long-running piece of JS and offer to shut it down.
Instead, you need to use a callback function on the setTimeout() and continue your code from that callback. You can't use sequential code for timeouts. You must use asynchronous coding styles.
You could do something like this where you pass in a callback and it calls the callback back and passes it the connected boolean:
function GetConnectedState(callback) {
setTimeout(function() {
callback(navigator.connection.type !== Connection.NONE);
}, 500);
}
Your existing code doesn't seem to offer anything other than a look at the connection state in 1/2 second. With any real sort of asynchronous operation in javascript (such as an ajax call or a websocket connection), there should also be a success or completion callback that will tell you when/if the operation actually completes and you can also trigger the callback based on that (sooner than 1/2 second most of the time). So, this doesn't really look like a complete solution, but it's all you show us you're using.
For example, here's an answer you can look at that calls a callback when an images loads successfully, with an error or times out with no response: Javascript Image Url Verify and How to implement a "function timeout" in Javascript - not just the 'setTimeout'. A similar concept could be used for implementing your own timeout on some other type of asynchronous call.
As I revisit this 5 years later, can't help but to offer up a fancier alternative:
await new Promise(function(resolve) {
setTimeout(resolve, 500);
});
if (navigator.connection.type === Connection.NONE) {
alert('Not Connected');
}
Javascript is single-threaded. The timeout function can't run until your script returns to the main event loop. But as long as you're in the while loop it will never return, so the timeout function never runs, so done is never set to true.
It's not possible in Javascript to wait for an asynchronous event before returning.
If I need call this functions one after other,
$('#art1').animate({'width':'1000px'},1000);
$('#art2').animate({'width':'1000px'},1000);
$('#art3').animate({'width':'1000px'},1000);
I know in jQuery I could do something like:
$('#art1').animate({'width':'1000px'},1000,'linear',function(){
$('#art2').animate({'width':'1000px'},1000,'linear',function(){
$('#art3').animate({'width':'1000px'},1000);
});
});
But, let's assume that I'm not using jQuery and I want to call:
some_3secs_function(some_value);
some_5secs_function(some_value);
some_8secs_function(some_value);
How I should call this functions in order to execute some_3secs_function, and AFTER that call ends, then execute some_5secs_function and AFTER that call ends, then call some_8secs_function?
UPDATE:
This still not working:
(function(callback){
$('#art1').animate({'width':'1000px'},1000);
callback();
})((function(callback2){
$('#art2').animate({'width':'1000px'},1000);
callback2();
})(function(){
$('#art3').animate({'width':'1000px'},1000);
}));
Three animations start at same time
Where is my mistake?
In Javascript, there are synchronous and asynchronous functions.
Synchronous Functions
Most functions in Javascript are synchronous. If you were to call several synchronous functions in a row
doSomething();
doSomethingElse();
doSomethingUsefulThisTime();
they will execute in order. doSomethingElse will not start until doSomething has completed. doSomethingUsefulThisTime, in turn, will not start until doSomethingElse has completed.
Asynchronous Functions
Asynchronous function, however, will not wait for each other. Let us look at the same code sample we had above, this time assuming that the functions are asynchronous
doSomething();
doSomethingElse();
doSomethingUsefulThisTime();
The functions will be initialized in order, but they will all execute roughly at the same time. You can't consistently predict which one will finish first: the one that happens to take the shortest amount of time to execute will finish first.
But sometimes, you want functions that are asynchronous to execute in order, and sometimes you want functions that are synchronous to execute asynchronously. Fortunately, this is possible with callbacks and timeouts, respectively.
Callbacks
Let's assume that we have three asynchronous functions that we want to execute in order, some_3secs_function, some_5secs_function, and some_8secs_function.
Since functions can be passed as arguments in Javascript, you can pass a function as a callback to execute after the function has completed.
If we create the functions like this
function some_3secs_function(value, callback){
//do stuff
callback();
}
then you can call then in order, like this:
some_3secs_function(some_value, function() {
some_5secs_function(other_value, function() {
some_8secs_function(third_value, function() {
//All three functions have completed, in order.
});
});
});
Timeouts
In Javascript, you can tell a function to execute after a certain timeout (in milliseconds). This can, in effect, make synchronous functions behave asynchronously.
If we have three synchronous functions, we can execute them asynchronously using the setTimeout function.
setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);
This is, however, a bit ugly and violates the DRY principle[wikipedia]. We could clean this up a bit by creating a function that accepts an array of functions and a timeout.
function executeAsynchronously(functions, timeout) {
for(var i = 0; i < functions.length; i++) {
setTimeout(functions[i], timeout);
}
}
This can be called like so:
executeAsynchronously(
[doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);
In summary, if you have asynchronous functions that you want to execute syncronously, use callbacks, and if you have synchronous functions that you want to execute asynchronously, use timeouts.
This answer uses promises, a JavaScript feature of the ECMAScript 6 standard. If your target platform does not support promises, polyfill it with PromiseJs.
Look at my answer here Wait till a Function with animations is finished until running another Function if you want to use jQuery animations.
Here is what your code would look like with ES6 Promises and jQuery animations.
Promise.resolve($('#art1').animate({ 'width': '1000px' }, 1000).promise()).then(function(){
return Promise.resolve($('#art2').animate({ 'width': '1000px' }, 1000).promise());
}).then(function(){
return Promise.resolve($('#art3').animate({ 'width': '1000px' }, 1000).promise());
});
Normal methods can also be wrapped in Promises.
new Promise(function(fulfill, reject){
//do something for 5 seconds
fulfill(result);
}).then(function(result){
return new Promise(function(fulfill, reject){
//do something for 5 seconds
fulfill(result);
});
}).then(function(result){
return new Promise(function(fulfill, reject){
//do something for 8 seconds
fulfill(result);
});
}).then(function(result){
//do something with the result
});
The then method is executed as soon as the Promise finished. Normally, the return value of the function passed to then is passed to the next one as result.
But if a Promise is returned, the next then function waits until the Promise finished executing and receives the results of it (the value that is passed to fulfill).
It sounds like you're not fully appreciating the difference between synchronous and asynchronous function execution.
The code you provided in your update immediately executes each of your callback functions, which in turn immediately start an animation. The animations, however, execute asyncronously. It works like this:
Perform a step in the animation
Call setTimeout with a function containing the next animation step and a delay
Some time passes
The callback given to setTimeout executes
Go back to step 1
This continues until the last step in the animation completes. In the meantime, your synchronous functions have long ago completed. In other words, your call to the animate function doesn't really take 3 seconds. The effect is simulated with delays and callbacks.
What you need is a queue. Internally, jQuery queues the animations, only executing your callback once its corresponding animation completes. If your callback then starts another animation, the effect is that they are executed in sequence.
In the simplest case this is equivalent to the following:
window.setTimeout(function() {
alert("!");
// set another timeout once the first completes
window.setTimeout(function() {
alert("!!");
}, 1000);
}, 3000); // longer, but first
Here's a general asynchronous looping function. It will call the given functions in order, waiting for the specified number of seconds between each.
function loop() {
var args = arguments;
if (args.length <= 0)
return;
(function chain(i) {
if (i >= args.length || typeof args[i] !== 'function')
return;
window.setTimeout(function() {
args[i]();
chain(i + 1);
}, 2000);
})(0);
}
Usage:
loop(
function() { alert("sam"); },
function() { alert("sue"); });
You could obviously modify this to take configurable wait times or to immediately execute the first function or to stop executing when a function in the chain returns false or to apply the functions in a specified context or whatever else you might need.
I believe the async library will provide you a very elegant way to do this. While promises and callbacks can get a little hard to juggle with, async can give neat patterns to streamline your thought process. To run functions in serial, you would need to put them in an async waterfall. In async lingo, every function is called a task that takes some arguments and a callback; which is the next function in the sequence. The basic structure would look something like:
async.waterfall([
// A list of functions
function(callback){
// Function no. 1 in sequence
callback(null, arg);
},
function(arg, callback){
// Function no. 2 in sequence
callback(null);
}
],
function(err, results){
// Optional final callback will get results for all prior functions
});
I've just tried to briefly explain the structure here. Read through the waterfall guide for more information, it's pretty well written.
your functions should take a callback function, that gets called when it finishes.
function fone(callback){
...do something...
callback.apply(this,[]);
}
function ftwo(callback){
...do something...
callback.apply(this,[]);
}
then usage would be like:
fone(function(){
ftwo(function(){
..ftwo done...
})
});
Since you tagged it with javascript, I would go with a timer control since your function names are 3, 5, and 8 seconds. So start your timer, 3 seconds in, call the first, 5 seconds in call the second, 8 seconds in call the third, then when it's done, stop the timer.
Normally in Javascript what you have is correct for the functions are running one after another, but since it looks like you're trying to do timed animation, a timer would be your best bet.
asec=1000;
setTimeout('some_3secs_function("somevalue")',asec*3);
setTimeout('some_5secs_function("somevalue")',asec*5);
setTimeout('some_8secs_function("somevalue")',asec*8);
I won't go into a deep discussion of setTimeout here, but:
in this case I've added the code to execute as a string. this is the simplest way to pass a var into your setTimeout-ed function, but purists will complain.
you can also pass a function name without quotes, but no variable can be passed.
your code does not wait for setTimeout to trigger.
This one can be hard to get your head around at first: because of the previous point, if you pass a variable from your calling function, that variable will not exist anymore by the time the timeout triggers - the calling function will have executed and it's vars gone.
I have been known to use anonymous functions to get around all this, but there could well be a better way,
You could also use promises in this way:
some_3secs_function(this.some_value).then(function(){
some_5secs_function(this.some_other_value).then(function(){
some_8secs_function(this.some_other_other_value);
});
});
You would have to make some_value global in order to access it from inside the .then
Alternatively, from the outer function you could return the value the inner function would use, like so:
one(some_value).then(function(return_of_one){
two(return_of_one).then(function(return_of_two){
three(return_of_two);
});
});
ES6 Update
Since async/await is widely available now, this is the way to accomplish the same:
async function run(){
await $('#art1').animate({'width':'1000px'},1000,'linear').promise()
await $('#art2').animate({'width':'1000px'},1000,'linear').promise()
await $('#art3').animate({'width':'1000px'},1000,'linear').promise()
}
Which is basically "promisifying" your functions (if they're not already asynchronous), and then awaiting them
//sample01
(function(_){_[0]()})([
function(){$('#art1').animate({'width':'10px'},100,this[1].bind(this))},
function(){$('#art2').animate({'width':'10px'},100,this[2].bind(this))},
function(){$('#art3').animate({'width':'10px'},100)},
])
//sample02
(function(_){_.next=function(){_[++_.i].apply(_,arguments)},_[_.i=0]()})([
function(){$('#art1').animate({'width':'10px'},100,this.next)},
function(){$('#art2').animate({'width':'10px'},100,this.next)},
function(){$('#art3').animate({'width':'10px'},100)},
]);
//sample03
(function(_){_.next=function(){return _[++_.i].bind(_)},_[_.i=0]()})([
function(){$('#art1').animate({'width':'10px'},100,this.next())},
function(){$('#art2').animate({'width':'10px'},100,this.next())},
function(){$('#art3').animate({'width':'10px'},100)},
]);
I use a 'waitUntil' function based on javascript's setTimeout
/*
funcCond : function to call to check whether a condition is true
readyAction : function to call when the condition was true
checkInterval : interval to poll <optional>
timeout : timeout until the setTimeout should stop polling (not 100% accurate. It was accurate enough for my code, but if you need exact milliseconds, please refrain from using Date <optional>
timeoutfunc : function to call on timeout <optional>
*/
function waitUntil(funcCond, readyAction, checkInterval, timeout, timeoutfunc) {
if (checkInterval == null) {
checkInterval = 100; // checkinterval of 100ms by default
}
var start = +new Date(); // use the + to convert it to a number immediatly
if (timeout == null) {
timeout = Number.POSITIVE_INFINITY; // no timeout by default
}
var checkFunc = function() {
var end = +new Date(); // rough timeout estimations by default
if (end-start > timeout) {
if (timeoutfunc){ // if timeout function was defined
timeoutfunc(); // call timeout function
}
} else {
if(funcCond()) { // if condition was met
readyAction(); // perform ready action function
} else {
setTimeout(checkFunc, checkInterval); // else re-iterate
}
}
};
checkFunc(); // start check function initially
};
This would work perfectly if your functions set a certain condition to true, which you would be able to poll. Plus it comes with timeouts, which offers you alternatives in case your function failed to do something (even within time-range. Think about user feedback!)
eg
doSomething();
waitUntil(function() { return doSomething_value===1;}, doSomethingElse);
waitUntil(function() { return doSomethingElse_value===1;}, doSomethingUseful);
Notes
Date causes rough timeout estimates. For greater precision, switch to functions such as console.time(). Do take note that Date offers greater cross-browser and legacy support. If you don't need exact millisecond measurements; don't bother, or, alternatively, wrap it, and offer console.time() when the browser supports it
If method 1 has to be executed after method 2, 3, 4. The following code snippet can be the solution for this using Deferred object in JavaScript.
function method1(){
var dfd = new $.Deferred();
setTimeout(function(){
console.log("Inside Method - 1");
method2(dfd);
}, 5000);
return dfd.promise();
}
function method2(dfd){
setTimeout(function(){
console.log("Inside Method - 2");
method3(dfd);
}, 3000);
}
function method3(dfd){
setTimeout(function(){
console.log("Inside Method - 3");
dfd.resolve();
}, 3000);
}
function method4(){
console.log("Inside Method - 4");
}
var call = method1();
$.when(call).then(function(cb){
method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>