如何在执行之前保留setTimeout参数值?

时间:2013-12-03 17:01:59

标签: javascript settimeout

我有一些代码在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...

Code on fiddle

有什么想法吗?

3 个答案:

答案 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;

DEMO:http://jsfiddle.net/U59Hv/2/

答案 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);
}
它可能不是比接受的更好的答案,只是不同的想法。由于未创建函数,因此它也可以在循环中使用。 在我看来,代码在这方面更具可读性。