2011-07-13 13 views
8

Đây là Ajax của tôi:Ajax được gửi trên các kết quả trùng lặp "keyup" khi gõ nhanh!

$("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>"); 
       } 
      } 
     }); 
    } 
}); 

Khi tôi gõ chậm (chậm hơn sau đó một lá thư mỗi giây) tôi nhận được kết quả chính xác, khi tôi gõ nhanh hơn tôi nhận được 2 lần so với kết quả tương tự

dụ:
gõ chậm: res1 res2 res3
nhanh gõ: res1 res2 res3 res1 res2 res3

Ngoài ra, lời khuyên nào về việc cải thiện mã sẽ được hoan nghênh!

+0

Tôi ha (ve) d cùng một vấn đề! +1 – genesis

+0

Bạn không nên gọi .append() trong một vòng lặp. Tạo chuỗi và gọi .append() một lần, vì lý do hiệu suất. Mỗi khi bạn gọi .append(), trình phân tích cú pháp HTML phải hoạt động và trình duyệt phải vẽ lại một phần.Nó nhanh hơn để làm điều này một lần với một đoạn lớn hơn để làm điều này rất thường xuyên với khối nhỏ hơn. – ckruse

+0

@ckruse thanx, tôi chuyển sang $ .each và vẫn còn cùng một vấn đề, mặc dù bây giờ tôi có thể gõ nhanh hơn một chút để không có nó ... :) – ilyo

Trả lời

7

Thats những gì đang xảy ra (giả):

Khi bạn đang gõ chậm:

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

Khi bạn gõ nhanh:

.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 

Để giải quyết vấn đề bản sao , bạn sẽ muốn làm cho kết quả của bạn xóa/thêm hoạt động nguyên tử - sử dụng .replaceWith.

kết quả xây dựng HTML khối đầu tiên là chuỗi và sau đó làm .replaceWith thay vì .remove/.append:

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

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

Một vấn đề khác (không liên quan đến bản sao) có thể là kết quả cũ ghi đè lên phiên bản mới hơn mà đến sớm (vì AJAX không đồng bộ và máy chủ có thể đưa ra các phản hồi không theo thứ tự nhận được yêu cầu).

Một cách tiếp cận để tránh điều này đánh dấu được gắn khứ hồi (loại "số sê-ri") cho mỗi yêu cầu, và kiểm tra nó trong phản ứng:

//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 ... 
    } 
}); 

On phía máy chủ:

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); 
} 

Một cách tiếp cận sẽ là thực hiện .ajax() yêu cầu đồng bộ, thiết lập tùy chọn async tới false. Tuy nhiên điều này có thể tạm khóa trình duyệt trong khi yêu cầu được kích hoạt (xem docs)

Và cũng chắc chắn bạn nên giới thiệu thời gian chờ như algiecas gợi ý để giảm tải trên máy chủ (đây là vấn đề thứ ba, không liên quan đến các bản sao cũng không yêu cầu/lệnh trả lời).

+0

Tại sao có sự khác biệt giữa 'replace' và' remove/append'? Ngoài ra, bạn có ví dụ làm việc nào về điểm đánh dấu khứ hồi không? Tôi không hoàn toàn hiểu cách nó hoạt động. – ilyo

+0

bởi vì 2 'remove' /' append' khối với thời gian chặt chẽ có thể dẫn đến 'remove1remove2' /' append1append2' (gây ra vấn đề của bạn với bản sao), trong khi 'replaceWith' nút chuyển đổi nguyên tử DOM, vì vậy bạn sẽ nhận được kết quả 1 hoặc kết quả1 , nhưng không phải cả hai – lxa

+0

Về điểm đánh dấu khứ hồi: tôi sẽ thêm một số nhận xét vào câu trả lời sau vài phút. – lxa

1

Bạn nên tham gia một số thời gian chờ trước khi gọi ajax. Một cái gì đó như thế này sẽ hoạt động:

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 
}); 

Tôi hy vọng điều này sẽ hữu ích.

+0

thanx nhưng không, tôi nhận được kết quả chính xác tương tự chỉ với một thời gian :) – ilyo

Các vấn đề liên quan