2014-08-29 52 views
1

我正在嘗試構建一個自動完成的用戶界面。有一個輸入,其keyup函數執行ajax調用服務器以獲取最相關的數據。但是,如果用戶鍵入一個字,例如10個字符,則每個keyup都會發出一個ajax調用,並且我的對話框將刷新10次。執行當前的ajax調用並中止所有先前的調用

我嘗試使用abort()進行ajax調用。當我對之前的ajax調用進行中止時,不會進行調用,但仍然會在執行最後一個調用之前等待10個調用,這會使用戶體驗非常糟糕。

那麼有沒有一種方法可以執行當前的ajax調用,而不會從前一個延遲?

我的代碼的一部分:

var request_autocomplete=jQuery.ajax({}); 
$('.review_autocomplete').keyup(function() { 
    request_autocomplete.abort(); 
    request_autocomplete=jQuery.ajax({ 
     // DO something 
    }); 
}); 
+0

可能重複[jQuery的自動完成,可以給我時,我提出一個新的前一個AJAX調用停止?](http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-stopped-when-i-raise -a) – Farshad 2014-08-29 23:51:30

+0

我不使用JQuery自動完成 – 2014-08-30 00:18:45

回答

1

OP,這有兩個部分。第一個是你的放棄,看起來你已經擁有了。

第二個是在過程中引入寬恕。你想在用戶停止輸入時觸發,而不是每次按鍵。

您需要同時使用keyUp和keyDown。在keyUp上,設置一個超時來激發你的提交。給它也許700毫秒。在KeyDown上,清除超時。

var request_autocomplete=jQuery.ajax({}); 
    var forgiveness; 

    // first your AJAX routine as a function 
    var myServiceCall = function() { 
     request_autocomplete.abort(); 
     request_autocomplete=jQuery.ajax({ 
      // DO something 
    } 

    // keyup 
    $('.review_autocomplete').keyup(function() { 
     forgiveness = window.setTimeout(myServiceCall, 700); 

     }); 
    }); 

    // key down 
    $('.review_autocomplete').keydown(function() { 
     window.clearTimeout(forgiveness); 

     }); 
    }); 

這將完成在不斷設置超時火每次關鍵是,但每次一鍵被按下,這將取消暫停。這會使您的服務電話不會觸發,直到用戶停止鍵入或暫停太久。最終的結果是,你會結束一個很小的百分比的電話。

+0

你可以用一些相關的代碼來解釋這個嗎 – 2014-08-29 23:45:12

+1

是的 - 我會編輯和添加。 – 2014-08-29 23:45:54

0

你可以實現你在你的問題問的方式如下預防例如3個電話:

var calls = 0; 
$('.review_autocomplete').keyup(function() { 
    if (calls >3) { 
     request_autocomplete.abort(); 
     request_autocomplete=jQuery.ajax({ 
      // DO something 
     }); 
     calls = 0; 
    } 
    calls++; 
}); 

但這種方式不推薦,因爲當用戶想要輸入sample,而用戶輸入samp則輸入p ajax調用起來。並且當用戶類型le什麼也沒有發生!

如果您正在使用jquery​​3210 您可以使用

minLenght,所以你可以檢查文本框的當前lenght,當用戶鍵入至少3個字符,則必須調用Ajax請求。

delay(最後一次按鍵和Ajax調用之間。通常2-300ms應該做的)

和有關此問題的快速搜索後使用AjaxQueue

我發現這個link顯示的另一種方式,以防止多個ajax呼籲通過使用高速緩存自動完成

+0

這不會工作我猜是因爲用戶的打字速度將會比從服務器獲取時間更快。因此,它會導致我所有的請求超時 – 2014-08-29 23:16:31

+0

我認爲這個問題是重複的[http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-停時,我加註-A(http://stackoverflow.com/questions/4121963/jquery-autocomplete-can-i-have-the-previous-ajax-calling-stopped-when-i-raise-a ) – Farshad 2014-08-29 23:51:01

0

您可以使用globalTimeout變量,使用setTimeout()clearTimeout()重置。

var globalTimeout; 
$('.review_autocomplete').keydown(function(){ 
    if(globalTimeout)clearTimeout(globalTimeout); 
}).keyup(function(){ 
    globalTimeout = setTimeoout(function(){ 
    $.ajax({/* you know the drill */}); 
    }, 10); 
}); 

這樣的超時被清除,只要您的客戶端推送​​,但因爲你的客戶端釋放的關鍵onkeyup,因此如果沒有按鍵動作$.ajax()只會叫暫停重新一旦設置後,在這種情況下爲10毫秒。我承認,這不會阻止已經完成的$.ajax()呼叫,但它可能無關緊要,因爲它們發生的速度非常快,並且只要客戶端繼續鍵入,此示例就會阻止將來的$.ajax()呼叫。

0

嘗試

var count = { 
    "start": 0, 
    // future , by margin of `count.timeout` 
    "complete": 0, 
    // if no `keyup` events occur , 
    // within span of `count.timeout` 
    // `request_autocomplete()` is called 
    // approximately `2` seconds , below , 
    // adjustable 
    "timeout" : 2 
}; 
$('.review_autocomplete') 
.focus() 
.on("keyup", function (e) { 
    elem = $(this); 
    window.clearInterval(window.s); 
    window.s = null; 
    var time = function() { 
     var t = Math.round($.now()/1000); 
     count.start = t; 
     count.complete = t + count.timeout; 
    }; 
    time(); 
    var request_autocomplete = function() { 

     return jQuery.ajax({ 
      url: "/echo/json/", 
      type: "POST", 
      dataType: "json", 
      data: { 
       json: JSON.stringify({ 
        "data": elem.val() 
       }) 
      } 
      // DO something 
     }).done(function (data) { 
      window.clearInterval(s); 
      console.log("request complete", data); 
      $("body").append("<br /><em>" + data.data + "</em>"); 
      elem.val(""); 
      count.start = count.complete = 0; 
      console.log(count.start, count.complete); 
     }); 
    }; 
    window.s = setInterval(function() { 
     if (Math.round($.now()/1000) > count.complete) { 
      request_autocomplete(); 
      console.log("requesting data"); 
     }; 
    // increased to `1000` from `501` 
    }, 1000); 

}); 

的jsfiddle http://jsfiddle.net/guest271314/73yrndwy/

相關問題