我有一些代码在keypress上执行,并在用户输入时将数据保存到数据库。
我添加了一个带有clearTimeout的setTimeout函数,因此用户输入的每个字符都不会发送一个Ajax请求来保存数据。
虽然setTimeout对一个输入字段很有用,但如果用户决定快速切换输入字段(在setTimeout延迟之前),则传递给callSomeAjax的参数会在执行该函数之前发生变化。
正在发生的事情的简化版......
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...
有什么想法吗?
答案 0 :(得分:6)
较新的浏览器允许您将参数传递给setTimeout
,并在回调中检索它。
setTimeout(function(a){
return callSomeAjax(a);
}, 1000, a);
或者你可以将它绑定到函数
setTimeout(function(a){
return callSomeAjax(a);
}.bind(null, a), 1000);
除此之外,您还需要在新范围内使用值创建setTimeout
回调。
function callbackWithValue(a) {
return function() {
return callSomeAjax(a);
};
}
setTimeout(callbackWithValue(a), 1000);
或者如果你已经拥有了这个功能,并且没有别的东西可以通过,那么你可以让它更通用......
function callbackWithValue(fn) {
var args = [].slice.call(arguments, 1);
return function() {
return fn.apply(null, args);
};
}
setTimeout(callbackWithValue(callSomeAjax, a), 1000);
最后一个显示.bind()
函数的开头。它可以进一步扩展,以允许this
的绑定和绑定后传递的附加参数的串联。
答案 1 :(得分:5)
问题是setTimeout
直到1秒后才运行传入的函数。 a
发生了什么变化,因此当callSomeAjax(a)
运行时,a
处于新值。
您需要在调用a
之前捕获(在闭包中)setTimeout
的值。
var a = 1;
function show(a) {
console.log(a);
}
(function(a){
setTimeout(function () {
show(a)
}, 1000);
}(a));
a = 3;
答案 2 :(得分:0)
这可以工作,也可以在循环中使用。
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);
}