setTimeout的行为取决于传递的函数参数的不同

时间:2018-08-08 09:43:37

标签: javascript vue.js

我对搜索字段有一个简单的限制,可以确保不是每个按键都作为查询发送,它在按键后等待300毫秒后才提交。如果在300毫秒之前未检测到另一次按键操作,则时钟将重置。

我在Vue中进行了如下设置:

<input v-model="search_string" placeholder="Search..." type="text" @keyup="searchThrottle();">

runSearch (type) {
    do something....
}

searchThrottle () {
    if (window.ajaxtimeout) clearTimeout(window.ajaxtimeout)

    window.ajaxtimeout = setTimeout(this.runSearch, 300)
},

根据此行,其工作方式有所不同:window.ajaxtimeout = setTimeout(this.runSearch, 300)

例如,如果我通过一个参数使行为window.ajaxtimeout = setTimeout(this.runSearch('autocomplete'), 300),则每次按键都会运行搜索,而忽略超时。

为什么功能不同?

5 个答案:

答案 0 :(得分:5)

如果将this.runSearch('autocomplete')放在setTimeout中,则runSearch函数将立即执行,而不是在预期的300ms之后执行。

因此,您可以将runSearch函数的参数添加到setTimeout初始化中:

setTimeout(this.runSearch, 300, 'autocomplete');

或者您可以使用闭包,但需要在之前存储this

var self = this;
setTimeout(function {
    self.runSearch('autocomplete');
}, 300);

就像@JaromandaX在评论中提到的那样,您可以使用ECMAScript 6做同样的事情:

setTimeout(() => this.runSearch('autocomplete'), 300); 

还有另一种使用.bind()创建函数引用的方法,该方法将this和其他参数传递给runSearch函数。这也很好,但是对我来说有点 。由于维护和可读性,我个人不喜欢这种环境。但是要获得最完整的答案,我也添加了该示例(第一篇帖子来自@BrotherWoodrow关于此问题):

setTimeout(this.runSearch.bind(this, 'autocomplete'), 300);

More information about setTimeout on MDN.

答案 1 :(得分:2)

  

setTimeout(函数,毫秒,param1,param2,...)

在IE9和更早版本中不支持setTimeout函数的参数。要解决此问题,您可以使用currying。

var that = this;
    myCustomSearch(type){
        return function(){
        that.runSearch(type)
        }
    }


    setTimeout(this.myCustomSearch('autocomplete'), 300)

答案 2 :(得分:1)

因为setTimeout需要一个函数 reference 。如果您输入this.runSearch(),它将立即执行。要创建函数引用并传递参数,请使用bind

window.ajaxtimeout = setTimeout(this.runSearch.bind(this, 'autocomplete'), 300)

如果您使用Lodash,它就具有throttle功能。

答案 3 :(得分:1)

在第一个版本中,您要告诉浏览器等待300毫秒,然后调用this.runSearch()

在第二个变体中,您将参数传递给函数,是告诉浏览器运行this.runSearch('autocomplete')

如果您希望在仍使计时器工作的同时将参数传递到this.runSearch函数中,则可以将其包装在函数中:

function runDelayedSearch(){
  this.runSearch('autocomplete');
}
window.ajaxtimeout = setTimeout(runDelayedSearch, 300)

您可以在ES6中使用以下命令更简洁地​​做到这一点:

window.ajaxtimeout = setTimeout(() => runSearch('autocomplete'), 300)

答案 4 :(得分:-1)

您可以使用如下绑定函数:

setTimeout(this.runSearch.bind(this, 'autocomplete'), 300)

这不会在实例化时执行功能