快速打字时,Ajax发送“keyup”重复结果!

这是我的Ajax:

$("form[0] :text").live("keyup", function(event) {

    event.preventDefault();
    $('.result').remove();
    var serchval = $("form[0] :text").val();

    if(serchval){

        $.ajax({

            type: "POST",
            url: "<?= site_url('pages/ajax_search') ?>",
            data: {company : serchval},
            success: function(data) {

                var results = (JSON.parse(data));
                console.log(results);

                if(results[0]){
                    $.each(results, function(index) {
                        console.log(results[index].name);
                        $("#sresults").append("<div class='result'>" + results[index].name + "</div>");
                    });
                }
                else {
                    $("#sresults").append("<div class='result'>לא נמצאו חברות</div>");
                }
            }
        });
    }
});

当我慢慢输入(慢于每秒一个字母)时,我得到的结果是正确的,当我输入更快时,我得到相同结果的2倍

例:
慢打字:res1 res2 res3
快速输入:res1 res2 res3 res1 res2 res3

此外,欢迎任何改进代码的建议!

多数民众赞成在发生什么(伪代码):

当你打字慢时:

.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
.append1
.keyup2
.remove2
//asynchronous ajax2 request takes some time here...
.append2

当您快速输入时:

.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
//and keyup2 happens before ajax1 is complete
.keyup2
.remove2
.append1
//asynchronous ajax2 request takes some time here...
.append2
//two results were appended _in a row_ - therefore duplicates

要解决重复问题,您可能希望使用.replaceWith使结果删除/附加原子操作.

构建结果HTML首先作为字符串阻塞,然后执行.replaceWith而不是.remove / .append:

var result = '';
for (i in results) {
    result += "<div class='result'>" + results[i].name + "</div>";
}

$("#sresults").replaceWith('<div id="sresults">' + result + '</div>');

另一个问题(与重复无关)可能是较旧的结果会覆盖较早到达的较新结果(因为AJAX是异步的,服务器可能会发出响应,而不是以接收请求的相同顺序).

避免这种情况的一种方法是将往返标记(一种“序列号”)附加到每个请求,并在响应中检查它:

//this is global counter, you should initialize it on page load, global scope
//it contains latest request "serial number"
var latestRequestNumber = 0;

$.ajax({
    type: "POST",
    url: "<?= site_url('pages/ajax_search') ?>",
    //now we're incrementing latestRequestNumber and sending it along with request
    data: {company : serchval, requestNumber: ++latestRequestNumber},
    success: function(data) {
        var results = (JSON.parse(data));
        //server should've put "serial number" from our request to the response (see PHP example below)
        //if response is not latest (i.e. other requests were issued already) - drop it
        if (results.requestNumber < latestRequestNumber) return;
        // ... otherwise, display results from this response ...
    }
});

在服务器端:

function ajax_search() {
    $response = array();

    //... fill your response with searh results here ...

    //and copy request "serial number" into it
    $response['requestNumber'] = $_REQUEST['requestNumber'];

    echo json_encode($response);
}

另一种方法是使.ajax()请求同步,将async选项设置为false.但是,这可能会在请求处于活动状态时暂时锁定浏览器(请参阅docs)

而且你也应该引入超时,因为algiecas建议减少服务器上的负载(这是第三个问题,与重复或请求/响应顺序无关).

相关文章
相关标签/搜索