jquery ui autocomplete:如何在文本输入失去焦点后取消缓慢的ajax请求

发布于 2024-12-09 17:09:30 字数 1326 浏览 0 评论 0原文

我正在使用 JQuery UI 自动完成字段,该字段与 ajax 查找相关,有时可能会相当慢。有时,用户会在 ajax 查询启动之后、ajax 调用返回之前离开文本输入字段。发生这种情况时,即使文本输入不再具有焦点,也会出现自动完成弹出窗口,并且关闭弹出窗口的唯一方法是选择一个项目(而不是按 Tab 键切换到另一个字段)。

事实上,这个 jquery ui demo 表现出相同的行为(例如输入 'ariz'进入文本字段,等待“搜索”动画出现,然后在返回任何结果之前按 Tab 键退出该字段)。

一种有效的解决方案(但感觉像是黑客)是检查ajax的成功回调以查看文本字段是否仍然具有焦点,如果不使用空列表调用response(),例如:

        $( "#city" ).autocomplete({
        var elem = this.element;
        source: function( request, response ) {
            $.ajax({
                url: "http://ws.geonames.org/searchJSON",
                data: {name_startsWith: request.term},
                success: function( data ) {
                    if(!$(elem).is(':focus') {
                        response({});
                        return;
                    }
                    response( $.map( data.geonames, function( item ) {
                        return {
                            label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
                            value: item.name
                        }
                    }));
                }
            });
        }
    });

是否有更优雅的方法解决方案?理想情况下,我想在用户从文本输入字段移开时立即取消 ajax 请求。

I'm using an JQuery UI Autocomplete field that is tied to an ajax lookup that can be rather slow at times. Occasionally a user will tab away from the text input field after the ajax query initiates but before the ajax call returns. When this happens, the autocomplete pop-up appears even though the text input no longer has focus, and the only way to dismiss the popup is by selecting an item (rather than tabbing to another field).

In fact, this jquery ui demo exhibits the same behavior (for example enter 'ariz' into the text field, wait for the 'searching' animation to appear and then tab out of the field before it returns any results).

One solution that works (but feels like a hack) is to check in the ajax's success callback to see if the text field still has focus, and if not to call response() with an empty list, for example:

        $( "#city" ).autocomplete({
        var elem = this.element;
        source: function( request, response ) {
            $.ajax({
                url: "http://ws.geonames.org/searchJSON",
                data: {name_startsWith: request.term},
                success: function( data ) {
                    if(!$(elem).is(':focus') {
                        response({});
                        return;
                    }
                    response( $.map( data.geonames, function( item ) {
                        return {
                            label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName,
                            value: item.name
                        }
                    }));
                }
            });
        }
    });

Is there a more graceful solution? Ideally I'd like to cancel the ajax request as soon as the user tabs away from the text input field.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

五里雾 2024-12-16 17:09:30

$.ajax 返回一个 jqXHR 对象,并且对象公开底层 XMLHttpRequest< 的 abort 方法 /代码> 对象。因此,您只需隐藏 jqXHR 并在正确的时间中止请求。也许是这样的:

source: function(request, response) {
    var $this = $(this);
    var $element = $(this.element);
    var jqXHR = $element.data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $element.data('jqXHR', $.ajax({
        // ...
        complete: function() {
            // This callback is called when the request completes
            // regardless of success or failure.
            $this.removeData('jqXHR');
            // And dismiss the search animation.
            response({});
        }
    });
}

然后你想要一些关于#city的东西:

$('#city').blur(function() {
    var $this = $(this);
    var jqXHR = $(this).data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $this.removeData('jqXHR');
});

在自动完成器的正常操作期间有时会出现短暂的模糊/焦点,但只有当有人从列表中选择某些内容时才会发生这种情况;当发生这种情况时,不应该运行 $.ajax 请求,因此我们不需要担心它。如果我错了,那么您可以通过在 blur 处理程序中使用计时器并在 focus 回调中取消计时器来解决它(您可以将计时器 ID 存储在另一个 .data() 插槽也是如此)。

我还没有测试过这个,但我很确定它会起作用。

$.ajax returns a jqXHR object and that object exposes the abort method of the underlying XMLHttpRequest object. So, you just need to stash the jqXHR and abort the request at the right time. Something like this perhaps:

source: function(request, response) {
    var $this = $(this);
    var $element = $(this.element);
    var jqXHR = $element.data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $element.data('jqXHR', $.ajax({
        // ...
        complete: function() {
            // This callback is called when the request completes
            // regardless of success or failure.
            $this.removeData('jqXHR');
            // And dismiss the search animation.
            response({});
        }
    });
}

And then you'd want some stuff on #city:

$('#city').blur(function() {
    var $this = $(this);
    var jqXHR = $(this).data('jqXHR');
    if(jqXHR)
        jqXHR.abort();
    $this.removeData('jqXHR');
});

There is a brief blur/focus sometimes during the autocompleter's normal operation but that only happens when when someone chooses something from the list; there shouldn't be a $.ajax request running when that happens so we don't need to worry about it. If I'm wrong then you can kludge around it by using a timer inside the blur handler and cancelling the timer in a focus callback (you could store the timer-ID in another .data() slot too).

I haven't tested this but I'm pretty sure it will work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文