2012-10-22 35 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()的一切,只有匹配的元素。

相关问题