2012-10-22 33 views
2

我有一個jQuery腳本,在DOM中搜索並在列表中顯示結果。如何平滑需要時間執行的jQuery腳本?

這裏有腳本的簡化版本:http://jsfiddle.net/FuJta/1/

通常有大量結果,因此該腳本可能需要一段時間來執行。 (在上面的例子中,這是用延遲腳本的函數來模擬的)。因此,如果您在搜索框中鍵入的速度太快,腳本會阻止您輸入,並且感覺不好。

如何更改我的腳本,以便您可以自由輸入,並在結果準備就緒時顯示結果。我想要一些類似facebook的搜索:如果輸入速度太快,結果只是延遲,但仍然可以輸入。

的Html

<p>Type in foo, bar or baz for searching. It works, but it is quite slow.</p><br/> 
<input type="text" id="search"/> 

<div id="container" style="display:none"> 
    <div class="element">foo</div> 
    <div class="element">bar</div> 
    <div class="element">baz</div> 
</div> 


<div id="results"> 
</div>​ 

的Javascript

$(function() { 
    function refreshResults() { 
     var search = $('#search').val(); 
     var $filtered = $('#container .element').clone().filter(function() { 
      var info = $(this).text(); 
      return info.toLowerCase().indexOf(search) >= 0; 
     }); 
     $('#results').empty(); 
     $filtered.each(function() { 
      $('#results').append($(this)); 
     }); 
    } 

    // simulating script delay 
    function pausecomp(millis) { 
     var date = new Date(); 
     var curDate = null; 
     do { 
      curDate = new Date(); 
     } 
     while (curDate - date < millis); 
    } 

    $('#search').keyup(function() { 

     pausecomp(700); 
     refreshResults(); 
    }); 
});​ 

一種解決方案可以只按下輸入時刷新結果。這樣,搜索結果的延遲感覺很好。但我寧願只是推遲結果,讓用戶自由輸入。

+5

可能的重複http://stackoverflow.com/questions/5913181/how-to-delay-keypress-function-when-user-is-typing-so-it-doesnt-fire-a-request – Marc

+0

啊,有我正要發佈的答案;)嘆息..那些重複..:D – dbf

+0

爲什麼你不看看自動完成功能是如何工作的,我想你正試圖在這裏創建相同的結果。可能會有幫助。 – Pratik

回答

2

您應該使用異步技術執行像這樣的搜索。毫無疑問,Facebook使用某種AJAX來請求搜索結果 - 這意味着從服務器獲取結果。這將有助於防止您目前遇到的用戶界面「凍結」。

這裏是你可以嘗試什麼一個非常簡單的例子(它用了jQuery的AJAX請求):

var searchInProgress = false;//used to work out if a search is in progress 
var searchInQueue = false;//used to flag if the input data has changed 

function getSearchResults(searchText){ 
    if (searchInProgress) { 
     searchInQueue = true; 
     return; 
    } 

    searchInProgress = true; 
    searchInQueue = false; 

    $.getJSON("URL",//URL to handle AJAX query 
     { searchText: searchText},//URL parameters can go here 
     function (data) { 
     //handle your returned data here 

     searchInProgress = false; 

     if (searchInQueue){//text has changed, so search again 
      getSearchResults(); 
     } 
     }); 
} 

$('#search').keyup(function() { 
     getSearchResults($(this).val()); 
}); 

有幾件事情需要注意:這可能是處理失敗的AJAX請求是一個好主意確保您可以根據需要重置searchInProgress標誌。此外,您可以根據需要在keyup之後添加延遲,但這完全取決於您希望如何工作。

1

Here's a solution將搜索過程分成若干步驟,在流程中返回流程以允許UI響應。

$(function() { 

    function searchFunc($element,search) { 
     var info = $element.text(); 
     return info.toLowerCase().indexOf(search) >= 0; 
    } 

    var searchProcessor = null; 
    function restartSearch() { 
     console.log('Restarting...'); 

     // Clear previous 
     if (searchProcessor != null) { 
      clearInterval(searchProcessor); 
     } 
     $('#results').empty(); 

     // Values for the processor 
     var search = $('#search').val(); 
     var elements = $('#container .element').get(); 
     console.log('l:',elements,elements.length); 

     // Start processing 
     searchProcessor = setInterval(function() { 
      if (elements.length == 0) { 
       // Finished searching all elements 
       clearInterval(searchProcessor); 
       searchProcessor = null; 
       console.log('Finished.'); 

      } else { 
       console.log('Checking element...'); 
       var $checkElement = $(elements.shift()); 
       if (searchFunc($checkElement, search)) { 
        $('#results').append($checkElement.clone()); 
       } 
      } 
     }, 10); 
    } 

    $('#search').keyup(function() { 
     restartSearch() 
    }); 
}); 

它每次只處理一個元素。這應該會增加,所以它每次可能處理10或100個,但重要的一點是,該作品被分成幾塊。

這個解決方案也應該比原來的更快,因爲它不是clone()的一切,只有匹配的元素。

相關問題