Why doesn't this function return true?
function test(str) {
window.setTimeout(function() {
if(str == 'ok') {
return true;
}
}, 1000);
}
console.log(test('ok'));
That's not exactly what i want to do.
I have a function nammed test() who does some actions after 1 second.
I want to execute next function, when test() is finished (so after the timeout).
How i can know when test i finished ?
Tracing your code, here's what happens.
test() is invoked.
setTimeout schedules a function to be called 1000 ms later.
test() concludes execution, no return statement was executed, so undefined is returned instead.
about 1000 ms later the scheduled function fires.
The scheduled function returns true to nothing.
In other words, it just doesn't work that way. The JS interpreter does not pause, it continues over the timeout. You cannot pause execution in JS.
Instead you typically use callbacks:
function test(str, callback) {
window.setTimeout(function() {
if (str === 'ok') {
callback(true);
}
}, 1000);
}
// logs 'true' 1000 ms later
test('ok', function(result) {
console.log(result);
});
// logs nothing, callback never fires
test('NOTOK!', function(result) {
console.log(result);
});
This code will do more what you seem to have expected.
It does not return true because the setTimeout call is asynchronous. Also, the return value true in your code comes from an inner function.
The normal way of handling such program flow is to pass a callback to the asynchronous function.
function test(str, callback) {
window.setTimeout(function() {
callback(str == 'ok');
}, 1000);
}
test('ok', function (result) {
console.log(result);
});
The function passed as the second argument to test() will be called when setTimeout executes the code. The argument to the callback function will tell if str is was ok or not.
For starters, settimeout is an asynchronous method, so the actual function test() will have finished and returned before the settimout code runs.
Secondly however, you are only returning true from the settimeout function not the test function, so you will never get anything other than false.
It doesn't return true because asynchronous function setTimeout() will execute after 1000 ms and console.log will execute in normal fashion without waiting of your 'test' function.
Related
Recently, I've tried to understand callback functions in JavaScript, however, this concept is still far away from my understanding. I have code like this:
function exampleFunc(callback) {
console.log("Starting...");
setTimeout(() => {
console.log("Logged after 3 secs.");
}, 3000);
callback();
}
function displayMessage() {
console.log("Log it!");
}
exampleFunc(() =>
{
console.log("Further code.");
});
displayMessage();
I've expected that after calling exampleFunc(), program will wait 3 seconds, and then call the callback and rest of code. But instead, the sequence of code is:
Starting...
Further code.
Log it!
Logged after 3 secs.
Why does it happen? I've expected that program will output "Starting", then wait and log "Logged after 3 secs.", then go to callback and output "Further code", and in the end, "Log it!".
Calling a setTimeout does not cause further execution of the code in that function to delay. setTimeout schedules a timeout, then continues executing the rest of the code in the function immediately.
You need to call callback inside the setTimeout callback, so that it runs only after the 3 seconds are up.
You also need to put the call of displayMessage inside the callback passed to exampleFunc.
function exampleFunc(callback) {
console.log("Starting...");
setTimeout(() => {
console.log("Logged after 3 secs.");
callback();
}, 3000);
}
function displayMessage() {
console.log("Log it!");
}
exampleFunc(() => {
console.log("Further code.");
displayMessage();
});
I'm having a synchronization and loading issues with some JS modules when the program starts. This error only shows up once at the beginning and then everything works, so it is an obvious sync problem.
The code:
//pyramid of doom
function initGame(){
initWorld(function(){
initPlayer(function(){
initBots(function(){
console.log("Game Loaded!");
update();
})
})
});
}
function initWorld(callback){
world.init(worldParams);
callback&&callback();
}
function initPlayer(callback){
player.init(scene,playerParams,world.getPhysicModel());
callback&&callback();
}
function initBots(callback){
bots.init(scene,botsParams,world.getPhysicModel());
callback&&callback();
}
function update() {
world.update(1/60);
player.update();
bots.update();
}
initGame();
The following is the error I'm getting.
Bots.js:112 Uncaught TypeError: Cannot read property 'mixer' of undefined
at Bots.update (Bots.js:112)
at update (Final.html:160)
What am I doing wrong? How can I synchronize the execution of the init functions?
(What I think that is going on is that the execution of initBots doesn't reach it end before the udpdate function starts to run.)
You can find the Bots.js module in my repository at ( 1 )
In bots.init you execute new THREE.ColladaLoader().load which looks to be asynchronous.
In its callback, you fill your _bots array (self._bots[modelLoaded] = bot;).
However, you execute bots.init() and do not wait for these asynchronous calls to complete before executing the initBots function callback. In the case of initGame execution, this callback executes update(), which in turn executes bots.update(), which tries to access this._bots[i].mixer with i index up to this._botsParams.length, i.e. a pre-defined value that does not account for how many items have been actually filled in _bots array.
Hence your error message: the array has no items yet at some indices, and trying to read a property on undefined throws an error.
Conclusion: common asynchronous issue.
You need to be passing the callbacks into the init functions. Guessing from a brief look at your bots code, they are not expecting to receive callbacks so you might be in for a rebuild.
You can't tell from the outside of an async function if it is done yet!
Equivalent to what you are doing:
let result = undefined
function takeTime () {
setTimeout(function() {
result = 'hello!'
}, 100)
}
function callback () {
console.log(result)
}
function run (callback) {
takeTime()
callback && callback()
}
run(callback) // undefined! takeTime has not finished yet
What you need to be doing:
let result = undefined
function takeTime (callback) {
setTimeout(function() {
result = 'hello!'
callback()
}, 100)
}
function callback () {
console.log(result)
}
function run (callback) {
callback && takeTime(callback)
}
run(callback) // 'hello!', the callback was only called once the takeTime function completed
How to execute asynchronous js code (written in node.js) every X seconds and ensure that the new execute/call won't be started before the callback (success, error) from asynchronous function is executed. Code example:
asyncFunc(function(successData){
// do something with successData
}, function(errorData){
// do something with errorData
});
setInterval comes to my mind firstly, but I think it won't ensure what I want, if the callback doesn't execute inside interval, it will go to the queue.
EDIT: To simplify case, repeat async function call 1 second after its callback finishes.
You can use setTimeout like this:
(function loop() {
asyncFunc(function(successData){
setTimeout(loop, X);
}, function(errorData){
// If you still want to continue:
setTimeout(loop, X);
});
})(); // execute immediately
This will start the delay when the async call triggers the callback.
Consider abstracting the problem with a re-usable method that'll allow you to specify the function to call, the interval at which it's called, and the callbacks to invoke:
function repeatAsync(func, interval, success, error) {
(function loop() {
func(
() => {
success();
setTimeout(loop, interval);
},
() => {
error();
setTimeout(loop, interval);
}
);
})(); // invoke immediately
}
If you want the chain of calls to be broken on error, replace the second argument to func with just error, i.e. func( () => { ... }, error)
I am new to javascript and I am trying to understand callbacks. I am not able to understand why 20 is getting printed before 10. My understanding is for a callback function like - func1(parameter,func2()) , func2() is the callback function, which gets executed after func1 executes with the "parameter" passed to func1. Is my understanding correct?
function timePass(length){
console.log("finished after doing timePass for "+length +" seconds")
}
timePass(10,timePass(20));
OUTPUT BELOW:
finished after doing timePass for 20 seconds
finished after doing timePass for 10 seconds
You are not really creating a callback function but actually calling timePass(20) before everything else on your last line of code.
To pass a callback function you should do something like this:
function timePass(length,callback){
console.log("finished after doing timePass for "+length +" seconds")
if(typeof(callback) == "function")
callback(20);
}
timePass(10,timePass);
This is because you execute the function timePass and then - adding the result as argument number 2.
Explaining what is happening:
First you define new function "timePass", The function printing on the console.
Second you execute timePass(10, /*But here you execute it again*/ timePass(20)).
The function timePass(20) will be executed first because you added ().
() == execute. If you just pass the name of the function, it will be passed as function. When you use () it will be executed and then the result will be passed as argument.
EXAMPLE OF USING CALLBACK
function timePass(length, callbackFunction){
console.log("finished after doing timePass for "+length +" seconds");
// check if the function caller is included callback parameter
// and check if it is function - to prevent errors.
if (callbackFunction && typeof callbackFunction == "function") {
// Execute the callback (timePass)
callbackFunction(20);
}
}
// Here you say, Execute timePass with arg 10, and then call timePass
timePass(10, timePass);
// and now callbackFunction defined above will be == timePass
// You can do also
timePass(10, anotherFunction)
// So another function will be executed after console.log()
USE CASES
Most often callbacks are used while we working with async code.
For example: Jsfiddle
// Imagine we have function which will request the server for some data.
function getData(index) {
// The request - response will took some time
// 0.1s ? 15s ? We don't know how big is the data we downloading.
var data;
// Imagine this is an AJAX call, not timeout.
setTimeout(function() {
// after 30ms we recieved 'server data'
data = 'server data';
},30)
return data;
}
var users = getData('users');
console.log(users); // undefined - because we returned "data" before the AJAX is completed.
/*
So we can change the function and adding an callback.
*/
function getAsyncData(index, callback) {
var data;
// Imagine this is an AJAX call, not timeout.
setTimeout(function() {
// after 30ms we recieved 'server data'
data = 'server data';
callback(data);
},30)
}
getAsyncData('users', function(data) {
console.log(data); // 'server data'
});
// OR
function processData(data) {
console.log(data);
}
getAsyncData('users', processData); // processData also logs 'server data'
basically when the interpreter is looking at this, it will call timepass(20) to evaluate the result (which is nothing as you have no return returning something), which then it tries to pass into the outer function.
i.e.
doFunction( doSomethingElse() );
if doSomethingElse returns 1, it must evaluate that before it can pass that 1 into doFunction.
Fundamentally, you have not actually passed a callback, you have called the function. Perhaps you meant:
callback = function() { somecode; }
target = function(data, callback) { console.log('hi'); callback(); }
target(10, callback);
notice the lack of () i.e. callback not callback()
I'm trying to get setTimeout to re-run the function it's inside after 15 seconds, it's not waiting 15 seconds and just doing it in a constant loop.
Here's my current code
function checkSession(x) {
http.abort();
http.open("GET", siteURL+"processes/ajax.php?call=check_session&string="+x+"&new="+Math.random(), true);
http.onreadystatechange = function() {
if(http.readyState == 4) {
if(http.responseText == true) {
updateSession(x);
} else {
setTimeout(checkSession(x),15000);
}
}
}
http.send(null);
}
I don't see any problems in the code itself, the only thing wrong is that it's just doing a constant loop without waiting the "15000" miliseconds.
change the setTimeout call to:
setTimeout(function(){checkSession(x)},15000);
As you have it now, checkSession is called immediately and then passed as an argument to setTimeout. Wrapping it inside the function allows for the call to be deferred.
Your explanation:
The function is like this: setTimeout( function, delay );
Your method call was not setting an anonymous function or reference to a function as the function argument.
Wrong: setTimeout(checkSession(x),15000);
Reason: checkSession(x) is a function call, not a reference to a function or anonymous function
Right: setTimeout(function() {checkSession(x) },15000);
Reason: the function call is now wrapped as an anonymous function in place and the function argument is set for the setTimeout( function, delay ) method.
Hope that helps to clear it up for you!