我可以延迟 jquery 的 keyup 事件吗?

Posted

技术标签:

【中文标题】我可以延迟 jquery 的 keyup 事件吗?【英文标题】:Can I delay the keyup event for jquery? 【发布时间】:2012-04-15 12:30:17 【问题描述】:

我将 rottentomatoes 电影 API 与 twitter 的 typeahead 插件结合使用,使用 bootstrap 2.0。我已经能够整合 API,但我遇到的问题是,在每个 keyup 事件之后,API 都会被调用。这一切都很好而且很花哨,但我宁愿在稍停片刻后拨打电话,让用户先输入几个字符。

这是我当前在 keyup 事件后调用 API 的代码:

    var autocomplete = $('#searchinput').typeahead()
    .on('keyup', function(ev)

        ev.stopPropagation();
        ev.preventDefault();

        //filter out up/down, tab, enter, and escape keys
        if( $.inArray(ev.keyCode,[40,38,9,13,27]) === -1 )

            var self = $(this);

            //set typeahead source to empty
            self.data('typeahead').source = [];

            //active used so we aren't triggering duplicate keyup events
            if( !self.data('active') && self.val().length > 0)

                self.data('active', true);

                //Do data request. Insert your own API logic here.
                $.getJSON("http://api.rottentomatoes.com/api/public/v1.0/movies.json?callback=?&apikey=MY_API_KEY&page_limit=5",
                    q: encodeURI($(this).val())
                , function(data) 

                    //set this to true when your callback executes
                    self.data('active',true);

                    //Filter out your own parameters. Populate them into an array, since this is what typeahead's source requires
                    var arr = [],
                        i=0;

                    var movies = data.movies;

                     $.each(movies, function(index, movie) 
                        arr[i] = movie.title
                        i++;
                     );

                    //set your results into the typehead's source 
                    self.data('typeahead').source = arr;

                    //trigger keyup on the typeahead to make it search
                    self.trigger('keyup');

                    //All done, set to false to prepare for the next remote query.
                    self.data('active', false);

                );

            
        
    );

是否可以设置一个小的延迟并避免在每次按键后调用 API?

【问题讨论】:

【参考方案1】:

可以这样轻松完成:

var autocomplete = $('#searchinput').typeahead().on('keyup', delayRequest);

function dataRequest() 
    // api request here


function delayRequest(ev) 
    if(delayRequest.timeout) 
        clearTimeout(delayRequest.timeout);
    

    var target = this;

    delayRequest.timeout = setTimeout(function() 
        dataRequest.call(target, ev);
    , 200); // 200ms delay

【讨论】:

这很好用,但似乎卡在一个循环中,每 200 毫秒调用一次 datarequest? 在您的代码中,您在 keyup 之后触发了 keyup:self.trigger('keyup')。对于正确的 keyup 事件处理,您应该删除 ev.stopPropagation();self.trigger('keyup')【参考方案2】:

一般来说,这可以通过setTimeoutclearTimeout 方法来实现:

var timer;

$('#textbox').keyup(function() 
    if (timer) 
        clearTimeout(timer);
    
    timer = setTimeout('alert("Something cool happens here....");', 500);
);

setTimeout 将在指定的毫秒间隔后执行提供的 javascriptclearTimeout 将取消此执行。

我还准备了jsFiddle demo,展示了运行中的代码 sn-p。

参考资料:

Javascript timing methods

【讨论】:

【参考方案3】:

对于使用 v0.11 of typeahead.js 并使用 Bloodhound 获取远程建议的人,您可以使用 rateLimitWait 选项来限制请求:

var search = new Bloodhound(
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: 
    url: '/search?q=%QUERY',
    rateLimitWait: 500
  
);

【讨论】:

【参考方案4】:

不确定 Bootstrap 2.0 使用哪个版本进行预输入,但 v0.9.3 有一个隐藏在后台的 minLength 选项,但没有记录。

$('#people').typeahead(
  name: 'people',
  prefetch: './names.json',
  minLength: 3
);

从这篇博文中发现:http://tosbourn.com/2013/08/javascript/setting-a-minimum-length-for-your-search-in-typeahead-js/

【讨论】:

【参考方案5】:

而不是延迟,如果您只想允许用户在 ajax $.getJSON 请求之前输入几个字符,您可以修改 if 语句,以便用户必须输入最少数量的字符,例如3、在请求数据之前:

if( !self.data('active') && self.val().length >=3)

【讨论】:

以上是关于我可以延迟 jquery 的 keyup 事件吗?的主要内容,如果未能解决你的问题,请参考以下文章

primefaces keyup 或其他 ajax 事件延迟

键控函数之间的 Jquery 延迟

jQuery 仅在附加了 jQuery 时才会触发 keyup 事件

在 JS/jQuery 中触发 keypress/keydown/keyup 事件?

jquery 键盘事件 keypress() keydown() keyup()

使用jquery获取keyup位置[重复]