javascript - setTimeout return - javascript

How can I use setTimeout if I want to return a value
$.each(pCodes, function(index, pCode) {
setTimeout(func(parm1), 2000);
});
function func(in)
{
var value = 999;
return value;
}

First of all, your call to setTimeout is wrong. You are calling the function func and then using the result in the setTimeout method. Your code is equivalent to:
$.each(pCodes, function(index, pCode) {
var temp = func(parm1);
setTimeout(temp, 2000);
});
As func returns 999, you will be doing setTimeout(999, 2000), which of course doesn't make sense. To call a function that takes a parameter from setTimeout you need a function that makes that function call:
$.each(pCodes, function(index, pCode) {
setTimeout(function() { func(parm1); }, 2000);
});
To handle the return value from func is a bit more complicated. As it's called later on, you have to handle the return value later on. Usually that is done with a callback method that is called when the return value is available:
var callback = function(value) {
// Here you can use the value.
};
$.each(pCodes, function(index, pCode) {
setTimeout(function() { func(parm1, callback); }, 2000);
});
function func(in, callback) {
var value = 999;
callback(value);
}

First of all, make sure you pass to setTimeout a function, in your example you passed undefined to it, as you func(param1) executes func directly. What you want is something like this:
setTimeout(function() { func(parm1); }, 2000);
And for 'returning' the value: Use some kind of callback function that is executed with the value when timeout expired. Like so:
function callback(value) {
// doSomethingWithNewValue
}
$.each(pCodes, function(index, pCode) {
setTimeout(function() { func(parm1, callback); }, 2000);
});
function func(in, callback)
{
var value = 999;
callback(value);
}
This is the general pattern used in such scenario (see event driven programming).

change it to :
var defValue;
$.each(pCodes, function(index, pCode) {
setTimeout(function(){defValue=func(parm1)}, 2000);
});
this way you can use the defValue in your function to access the returned value

It's pretty ugly, but you can use output parameters, since js objects are pass by reference:
function a() {
var param1 = 42;
var result = {};
b(param1, result);
}
function b(val, output) {
something();
output.returned = 4;
}
Or, you can use a callback (the better option):
function a() {
var param1 = 42;
b(param1, function (newVal) {
something();
});
}
function b(val, callback) {
//something
callback(4);
}
By the way, your call to setTimeout is wrong. setTimeout receives a function as a first parameter, and a delay as a second - the first argument is still seen as regular javascript code, so it evaluates it, so your setTimeout call turns out to be like this:
setTimeout(999, 2000);
Since you're returning 999 from the function.
However, setTimeout can also receive a list of arguments after the second parameter, so it can be turned into this:
setTimeout(func, 2000, param1);

Related

return statement dose not work with setTimeout()

Why the retrun statement will not return x:
function getData(cb) {
setTimeout(cb, 1000);
}
getData(function () {
var x = 10;
return x;
})
because your getData function is not returning anything.
setTimeout is calling another function which is returning something. and that is a different function. JS returned value for getData long before your function inside setTimeout will execute.
A callback function usually never return a value, instead the value is passed as an argument.
function getData(cb) {
setTimeout(function(){
var data = 'Here is the data';
cb(data);
}, 1000);
}
getData(function(data){
console.log(data);
});

Call back function throwing error

I'm trying to solve this async problem. I got the problem working.
However, after calling "done" callback it's throwing an error. I don't know why.
Issue:
I want to print the task number once "Done" is invoked.
But it throws an
error saying TypeError: "callback" argument must be a function
Problem:
A "TaskRunner" Constructor takes one argument, "concurrency", and
exposes one method "push" on its prototype. The "push" method takes
one argument "task" which is a "function"
Passing a task to a push method of a TaskRunner instance should
immediately execute (call/run/invoke) the task, unless the number
of currently running tasks exceeds the concurrency limit.
function TaskRunner(concurrency) {
this.count = concurrency;
this.queue = [];
}
TaskRunner.prototype.push = function(task) {
if (this.count === 0) {
this.queue.push(task);
} else {
this.invoke(task);
}
}
TaskRunner.prototype.invoke = function(task) {
task.call(null, this.done.bind(this));
this.count--;
}
TaskRunner.prototype.done = function(num) {
console.log(`After Executing done: ${num}`)
this.count++;
this.execute();
}
TaskRunner.prototype.execute = function() {
if (this.queue.length > 0) {
var task = this.queue.shift();
this.invoke(task);
}
}
function factory(num) {
return function exampleSimpleTask(done) {
this.num = num;
console.log("task", "Before " + new Date().getTime());
setTimeout(done(num), 2000);
}
}
var r = new TaskRunner(2);
r.push(factory(1));
r.push(factory(2));
r.push(factory(3));
EDIT: For some reason, on jsfiddle it runs fine but when I run the same code on my local it fails.
Please help.
You are passing the setTimeout the result of you function:
setTimeout(done(num), 2000);
This will call done(num) immediately and setTimeout will try to call whatever done() returned as through it were a function.
You should pass it a function that it can call instead:
setTimeout(() => done(num), 2000);
or [as #JaromandaX points out in the comment] you can take advantage of the options third argument of setTimeOut which will be passed into the callback function:
setTimeout(done, 2000, num);
this will call the function done and pass in num

Keeping the callback alive

I have a callback that gets tossed around a lot. I can't figure a way to keep it through all of functions.
function a(callback) {
callback();
}
var number = 0;
function b(callback) {
number++;
c(number, callback);
}
function c(number, callback) {
if (number != 2) {
a(function () {
b();
});
} else {
callback();
}
}
a(function() {
b(function() {
console.log('hi');
});
});
I need a way to get the outermost callback (the one with console.log) to the a() function and subsequently the b() function when I call the a() function in the c() function.
Let me know if this sounds like gibberish. I will try to clarify.
You are encountering a TypeError: undefined is not a function. This is because in c you're invoking b without passing any args so when number !== 2 you've lost your reference
I re-wrote your code and it ended up working
var number = 0;
function invoke(fn) { // do you really need this? just invoke directly
fn();
}
function count(fn) {
++number;
limit(number, fn);
}
function limit(num, fn) {
if (num < 2) // this is much safer
invoke(function () {
count(fn); // passing an arg here
});
else
fn();
}
invoke(function () {
count(function () {
console.log('hello world');
});
});
You're getting dangerously close to what is known as 'callback hell'. You'll want to avoid that if you can. Since I'm not 100% sure why you need to pass around so many callback functions, you can achieve what you're looking for by doing the following:
function increment(number, callback, callback2) {
console.log('Incrementing number ' + number + ' by 1');
number++;
callback(number, increment, callback2);
}
function verify(number, callback, callback2) {
if (number < 2) {
callback(number, verify, callback2);
} else {
callback2();
}
}
var number = 0;
increment(number, verify, function () {
console.log('Hello world!');
});
You'll notice that I renamed some functions and excluded your a() function since it did nothing but execute the callback function passed to it. Unless that function is to serve another purpose, it is useless. You also don't need to create an anonymous function every time you are passing a callback. To pass a previously defined function as a parameter or callback, simply pass the function name without the (). If you are passing an undefined function as a callback, you will need to create the anonymous function which is what is being done with the console.log() callback.
Here's a jsfiddle. You can open your console log and see what it's doing.
jsfiddle
Please also be sure to read up on callback hell and how to design your code in a way that it can be avoided. Call back hell

Inner function calling parent function with setTimeout

How can an inner function call a parent function after it has expired?
setTimeout(main, 2000);
function main(){
/* .... code */
setTimeout(console.log("hello after 5 seconds"), 5000);
}
The intended action is to print hello after 5 seconds in 5 seconds (7 total); with the above code it prints it in 2 seconds.
You need to pass setTimeout function references. With setTimeout(console.log("hello after 5 seconds"), 5000);, you call console.log immediately. Any time you write () after a function name, you're invoking it.
console.log returns undefined, which is what is passed to setTimeout. It just ignores the undefined value and does nothing. (And it doesn't throw any errors.)
If you need to pass parameters to your callback function, there are a few different ways to go.
Anonymous function:
setTimeout(function() {
console.log('...');
}, 5000);
Return a function:
function logger(msg) {
return function() {
console.log(msg);
}
}
// now, whenever you need to do a setTimeout...
setTimeout(logger('...'), 5000);
This works because invoking logger simply returns a new anonymous function that closes over msg. The returned function is what is actually passed to setTimeout, and when the callback is fired, it has access to msg via the closure.
I think I understood what you want. Take a look:
var main = function(){
console.log("foo");
var function1 = function( string ) {
console.log("function1: " + string);
};
var function2 = function() {
console.log( "hadouken!" );
};
// you will need to use a closure to call the function
// that you want with parameters
// if you dont have parameters, just pass the function itself
setTimeout(function(){ function1("bar") }, 5000);
setTimeout(function2, 6000);
}
setTimeout(main, 2000);
Or:
function main(){
console.log("foo");
function function1( string ) {
console.log("function1: " + string);
};
function function2() {
console.log( "hadouken!" );
};
// you will need to use a closure to call the function
// that you want with parameters
// if you dont have parameters, just pass the function itself
setTimeout(function(){ function1("bar") }, 5000);
setTimeout(function2, 6000);
}
setTimeout(main, 2000);
I usually prefer the first sintax.
jsFiddle: http://jsfiddle.net/davidbuzatto/65VsV/
It works! You miss word function.
setTimeout(main, 1000);
function main() {
function function1 () { alert(1); };
setTimeout(function1, 1000);
}​

SetTimeout Executing faster then assigned interval

I have assigned 5000 ms to Settimeout but it is executing before assigned time interval.Can any body explain why it is happening.
<script type="text/javascript">
var getcallback = {
closure: function (callback, functionparam) {
return callback.call(functionparam);
}
}
var cleartimeout;
var startSlideShow = {
timerid: 5000,
startAnimation: function () {
cleartimeout = setTimeout(getcallback.closure(function () {
alert("this is a basic example of chaining methods");
this.startAnimation();
},this), this.timerid);
},
stopAnimation:function(){
}
}
startSlideShow.startAnimation();
</script>
Because getcallback.closure() is executing the function right away, you are not storing a reference to a function to call at a later time.
As soon as you call startAnimation, you're calling getcallback.closure, which immediately calls the callback function. To use setTimeout correctly, you need to either have closure return a function, or not use such a strange thing, and instead just use an anonymous function.
Something along the lines of:
var getcallback = {
closure: function (callback, functionparam) {
return function() {
callback.call(functionparam);
};
}
}
...
Or, to be cleaner, just:
var cleartimeout;
var startSlideShow = {
timerid: 5000,
startAnimation: function () {
cleartimeout = setTimeout(function () {
alert("this is a basic example of chaining methods");
this.startAnimation();
}, this.timerid);
},
stopAnimation:function(){
}
}
startSlideShow.startAnimation();

Categories