I have a bit of code that executes on keypress and saves data to a database as the user types.
I added a setTimeout function with a clearTimeout infront of it so not EVERY single character the user enters is sending out an Ajax request to save data.
While the setTimeout works great for one input field , if the user decides to switch input fields quickly (before the setTimeout delay is up) the parameter passed to the callSomeAjax changes before the function is executed.
Simplified version of what's happening...
var a = 1; //some user data
//function to call ajax script to save data to database
function callSomeAjax(a)
{
console.log(a);
}
setTimeout(function(){callSomeAjax(a)},1000); //executes callSomeAjax after 1 second delay
a=3; //change user data before callSomeAjax executes
// Result of console.log is 3, not 1 like I want it to be...
Code on fiddle
Any ideas?
I have a bit of code that executes on keypress and saves data to a database as the user types.
I added a setTimeout function with a clearTimeout infront of it so not EVERY single character the user enters is sending out an Ajax request to save data.
While the setTimeout works great for one input field , if the user decides to switch input fields quickly (before the setTimeout delay is up) the parameter passed to the callSomeAjax changes before the function is executed.
Simplified version of what's happening...
var a = 1; //some user data
//function to call ajax script to save data to database
function callSomeAjax(a)
{
console.log(a);
}
setTimeout(function(){callSomeAjax(a)},1000); //executes callSomeAjax after 1 second delay
a=3; //change user data before callSomeAjax executes
// Result of console.log is 3, not 1 like I want it to be...
Code on fiddle
Any ideas?
Share Improve this question edited Dec 3, 2013 at 17:04 gen_Eric 227k42 gold badges303 silver badges342 bronze badges asked Dec 3, 2013 at 17:01 paylingpayling 2,5246 gold badges33 silver badges45 bronze badges 2- are you trying to do individual ajax updates for each input field, or does 1 ajax call save the entire form to the DB? – chiliNUT Commented Dec 3, 2013 at 17:06
- Don't use a global setTimeout, simply create one once the user starts typing, in the scope of the input that the user is typing in? – Mike 'Pomax' Kamermans Commented Dec 3, 2013 at 17:06
3 Answers
Reset to default 9Newer browsers will let you pass the argument to setTimeout
, and retrieve it in the callback.
setTimeout(function(a){
return callSomeAjax(a);
}, 1000, a);
Or you could bind it to the function
setTimeout(function(a){
return callSomeAjax(a);
}.bind(null, a), 1000);
Aside from those, you'd need to create the setTimeout
callback in a new scope with the value.
function callbackWithValue(a) {
return function() {
return callSomeAjax(a);
};
}
setTimeout(callbackWithValue(a), 1000);
Or if you already have the function as you do, and there's nothing else to pass, then you can make it more generic...
function callbackWithValue(fn) {
var args = [].slice.call(arguments, 1);
return function() {
return fn.apply(null, args);
};
}
setTimeout(callbackWithValue(callSomeAjax, a), 1000);
This last one is shows the beginnings of a .bind()
function. It can be further expanded to allow the binding of this
and the concatenation of additional arguments passed after the bound one.
The problem is that setTimeout
doesn't run the function passed in until 1 second has passed. What that does happen a
has changed, so when callSomeAjax(a)
is ran, a
is at its new value.
You need to capture (in a closure) the value of a
before calling setTimeout
.
var a = 1;
function show(a) {
console.log(a);
}
(function(a){
setTimeout(function () {
show(a)
}, 1000);
}(a));
a = 3;
DEMO: http://jsfiddle/U59Hv/2/
This works and can be also used within loop.
var x = "OK";
setTimeout(alertOK.bind(null,x), 3000);
x = "Would be WRONG";
console.log("before timeout:", x);
function alertOK(x){
console.log("after timeout:",x);
}
It might not be better answer than the accepted one, just different idea. Since function is not created, it can also be used in loops.
In my opinion, code is a bit more readable this way.