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

pay*_*ing 5 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...
Run Code Online (Sandbox Code Playgroud)

关于小提琴的代码

有任何想法吗?

Blu*_*ies 7

较新的浏览器允许您将参数传递给setTimeout,并在回调中检索它.

setTimeout(function(a){
    return callSomeAjax(a);
}, 1000, a);
Run Code Online (Sandbox Code Playgroud)

或者你可以将它绑定到函数

setTimeout(function(a){
    return callSomeAjax(a);
}.bind(null, a), 1000);
Run Code Online (Sandbox Code Playgroud)

除此之外,您还需要setTimeout在值的新范围内创建回调.

function callbackWithValue(a) {
    return function() {
        return callSomeAjax(a);
    };
}

setTimeout(callbackWithValue(a), 1000);
Run Code Online (Sandbox Code Playgroud)

或者,如果你已经拥有了这个功能,并且没有别的东西可以通过,那么你可以使它更通用......

function callbackWithValue(fn) {
    var args = [].slice.call(arguments, 1);
    return function() {
        return fn.apply(null, args);
    };
}

setTimeout(callbackWithValue(callSomeAjax, a), 1000);
Run Code Online (Sandbox Code Playgroud)

最后一个显示了.bind()函数的开头.它可以进一步扩展,以允许在绑定this之后传递的附加参数的绑定和连接.


Roc*_*mat 6

问题是,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;
Run Code Online (Sandbox Code Playgroud)

演示:http://jsfiddle.net/U59Hv/2/