【问题标题】:Use .abort() to cancel existing ajax request if user sends another如果用户发送另一个请求,请使用 .abort() 取消现有的 ajax 请求
【发布时间】:2013-11-12 17:12:50
【问题描述】:

我正在尝试关注the advice within this question 以适应以下情况:

在 keyup 时,向服务器发送一个 AJAX 请求,并在输入字段中包含术语。但如果他们继续输入,则中止任何现有的 AJAX 请求,因此只发送一个请求。

这是我的代码:

jQuery(document).ready(function($) {

    var $input      = $('#s'),
        inputVal    = '',
        inputCount  = '';

    function process_asr_request() {
        $.ajax({
            url: MyAjax.ajaxurl,
            data: {
                'action':'pondera_asr_request',
                'inputVal' : inputVal
            },
            success:function(data) {
                $('#search-results').append( data )
            },
            error: function(errorThrown){
                console.log( errorThrown);
            }
        });
    }

    $input.on("keyup", function() {
        // record the value of the input
        inputVal    = $input.val(),
        // check the lenght on the value
        inputCount  = inputVal.length,      
        // define array for ajax requests
        requests    = [];

        // Only process once there are 3 characters
        if (inputCount > 2) {
            // push ajax requests into the array
            requests.push(
                process_asr_request(i)
            );
            // loop through the array of requests
            for(
                var i = 0;
                i < requests.length;
                i++
            )
            // kill any queued requests
            requests[i].abort();
        };
    });
});

我有两个问题:

  1. 这种方法是否适用于我想要实现的目标
  2. 上面的代码出现“Uncaught TypeError: Cannot call method 'abort' of undefined”错误。我哪里错了。

我对 AJAX 还很陌生,所以请原谅我的幼稚。

【问题讨论】:

  • 返回process_asr_request()中的XHR
  • 没有必要中止它。您可以简单地忽略它,因为 AJAX 无论如何都是异步的。而不是requests,只需使用一个request 并在keyup 上覆盖之前的请求。
  • 为了更好的用户界面,考虑使用 333ms 超时和 oninput 而不是 onkeyup
  • 据我了解,oninput 还没有在 jQuery 中:stackoverflow.com/questions/11189136/…
  • 至于setTimeout 建议,您会建议在代码中的哪个位置包含它?在if (inputCount &gt; 2) { 语句中?

标签: javascript ajax performance jquery


【解决方案1】:

关闭,只需返回 xhr 即可中止它:

 function process_asr_request(inputVal) {
    return $.ajax({
        url: MyAjax.ajaxurl,
        data: {
            'action':'pondera_asr_request',
            'inputVal' : inputVal
        },
        success:function(data) {
            $('#search-results').append( data )
        },
        error: function(errorThrown){
            console.log( errorThrown);
        }
    });
}

此外,这个循环最好写成如下,所以旧的 xhrs 从请求中删除:

var xhr;
while (xhr = requests.pop()) {
        // kill any queued requests
        xhr.abort();
}
requests.push(process_asr_request(inputVal));

另外注意,如果你想让它工作,请求应该在事件循环之外并且你在这个函数中有几个全局变量

var requests = [];
$input.on("keyup", function() {
    var inputVal    = $input.val(),
    // check the lenght on the value
        inputCount  = inputVal.length;
    //...
});

【讨论】:

  • 感谢您的建议。但这似乎中止了我的所有请求。一旦用户停止输入,则不会发送任何内容。有什么想法吗?
  • 将上面的中止部分移动到请求数组中 - 我更新了第二个代码片段
  • 也刚刚更新它以将inputVal 传递给请求,您可能需要考虑更新您的代码以将inputVal 放在顶部范围内
  • 好的,这似乎有效,感谢您的深度回答!当您提到将“inputVal移入顶级范围”时,它是在原始代码的开头声明的......还是我没有关注你?
  • 它是如何工作的,但如果是我的代码,我可能只会在顶级范围内声明 $inputrequests
【解决方案2】:
var currXHR;

function process_asr_request() {

    if(currXHR && currXHR.abort) currXHR.abort();

    currXHR = $.ajax({
        url: MyAjax.ajaxurl,
        data: {
            'action':'pondera_asr_request',
            'inputVal' : inputVal
        },
        success:function(data) {
            $('#search-results').append( data )
        },
        error: function(errorThrown){
            console.log( errorThrown);
        }
    });
}

【讨论】:

  • 就绪状态无关紧要。当输入一个新字符时,应该发送一个新的请求,并且任何先前的请求,无论状态如何,都应该被取消。
  • 事实上,唯一不需要取消请求的情况是当 readyState 为 4... 因为在这种情况下没有什么可以取消的。
  • currXHR 将引用以前的 XHR,如果它存在的话。如果 readyState 为 == 4 可以忽略,否则需要取消。
  • 啊,好吧,我看错了条件...是的,但是如果 readyState 是 4,abort 只会默默地什么都不做(不会触发错误)。
  • 在这个例子中,我假设不再需要数组 & for 循环是否正确?
猜你喜欢
  • 2011-03-19
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 2017-06-14
  • 2019-10-15
  • 1970-01-01
相关资源
最近更新 更多