2011-07-13 19 views
8

这是我的Ajax:在“快捷键”上发送的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

此外,在提高代码的任何意见会受到欢迎!

+0

我哈(ve)d同样的问题! +1 – genesis

+0

您不应在循环中调用.append()。出于性能原因,创建一个字符串并调用.append()一次。每次调用.append()时,HTML解析器都必须工作,并且浏览器必须进行分区重绘。这样做比较快,一次只能用较大的块进行,而不能用较小的块进行。 – ckruse

+0

@ckruse thanx,我切换到$。每个仍然是同样的问题,虽然现在我可以输入一点速度没有它... :) – ilyo

回答

7

那是发生了什么(伪):

当你打字慢:

.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建议,以减少服务器负载你一定要引入超时(这是第三个问题,不涉及重复,也不要求/响应订单)。

+0

为什么'replace'和'remove/append'有区别?另外,你有任何一个往返标记的实例吗?我不完全理解它是如何工作的。 – ilyo

+0

,因为''remove'/'append' blocks with tight timing can result in'remove1remove2' /'append1append2'(which may cause with duplicates),while'replaceWith'自动切换DOM节点,所以你会得到result1或result1 ,但不是两个 – lxa

+0

关于往返标记:我会在几分钟内添加一些评论的答案。 – lxa

1

在调用ajax之前,您应该涉及一些超时。这样的事情应该工作:

var timeoutID; 

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

    clearTimeout(timeoutID); 

    timeoutID = setTimeout(function() 
    { 
     $('.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); 

        for (i in results) 
        { 
         console.log(results[i].id); 
         $("#sresults").append("<div class='result'>" + results[i].name + "</div>"); 
        } 
       } 
      }); 
     } 
    }, 1000); //timeout in miliseconds 
}); 

我希望这可以帮助。

+0

thanx但没有,我得到完全相同的结果只有超时:) – ilyo