加速 jQuery AutoComplete(不可避免的长列表)

Posted

技术标签:

【中文标题】加速 jQuery AutoComplete(不可避免的长列表)【英文标题】:Speeding up jQuery AutoComplete (Unavoidably long lists) 【发布时间】:2012-03-18 13:07:10 【问题描述】:

我今天下午早些时候开始了加速 jQuery 自动完成的旅程,并决定开始 memcaching 一切可能是个好主意。如本文所建议:Speeding up autocomplete。

但是,即使在安装和使用 Memcached 之后,我仍然会遇到响应时间缓慢的问题。

就我而言,问题在于我正在处理非常长的列表,就我而言,超过 6700 个个人成员。 (所有植物的所有属或属)

瓶颈似乎是在构建表和填充客户端列表,而不是从 Memcached 中检索信息造成的。

如果其他人遇到过这个特殊问题,我很想听听一个聪明的方法来解决它。我将在下面发布我的代码。

注意:此特定页面不对公众开放,我知道存在一些巨大的安全漏洞。


require_once 'oo/Database.php';

$mysqldb = new Database;

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect to memcache");

$sql = "SELECT DISTINCT `Genus` FROM importlist.plants";

$key = md5('query'.$sql);

$result = $memcache->get($key);


//check if we got something back
if($result == null) 

    //fetch from database
    $result = $mysqldb->rawSelect($sql)->getResult();

    //set to memcache, expires after 1 hour
    $memcache->set($key,$result,0,3600); 


//Result array
$Genera = ($memcache->get($key));

//Add required "quotation marks" for autocomplete
foreach ($Genera as &$Genus)
    $Genus = '"'.$Genus[Genus].'"';
 
$Genera = implode($Genera,',');

//PHP to generate jQuery    
echo <<< EOT

    <script>
    $(function() 
        var availableTags = [$Genera];
        $( "#tags" ).autocomplete(
            source: availableTags
        );
    );
    </script>
EOT;

?>

<input id="tags" />

【问题讨论】:

不知道这会加快速度,但您应该可以设置$Genera = $result 而不是第二次调用内存缓存。或者更好的是,只需在 foreach() 中使用 $result 而不是 $Genera 可以在页面加载后或用户尝试使用自动完成功能之前使用 ajax 请求来填充数据吗? 看起来您正在模拟创建数组的 json 表示法。可能json_encode 会给你比 foreach 更快的速度。但是,您应该首先找出该代码块的哪一部分消耗了这么多时间。首先通过运行一些指标来定位瓶颈。 XDebug 或许可以帮助您找到瓶颈所在。 【参考方案1】:

由于在用户输入至少 1 个字符之前您无法查找任何内容,因此您可以创建 26 个不同的列表。每个自动完成列表仅包含以该字母开头的项目。您的列表将明显更小,加载速度更快。

要使其更快,请创建更多列表。您可能只需要显示前 30-40 个项目。如果该项目不在缩短的列表中,用户很可能会键入另一个字母。然后,您可以将列表划分为 26*26 个唯一列表。每个列表仅包含以前 2 个字母开头的项目。

您可以根据需要将项目分成多个列表。我们在我管理的网站上执行此操作,我们的预输入中有超过 500,000 个可用项目。

【讨论】:

【参考方案2】:
$(document).ready(function() 

    // once page loads, make AJAX request to get your autocomplete list and apply to html
    $.ajax( url: '/path-to-get-tags-as-json.php',
        type: "GET",
        contentType: "application/json",
        success: function(tags) 
            $( "#tags" ).autocomplete(
                source: tags
            );
        
    );
);

将您的 PHP 文件的 URL 放置在上面的 AJAX 占位符 url 参数中生成自动完成列表。在您的 PHP 代码中,修改列表生成,使其返回一个 JSON 数组,如下所示:

[ "first" , "second" , "anotherEntry" , "in" , "the" , "array" ]    

肯定不会加快进程服务器端,但它保护您的用户在应用自动完成时不会出现一些延迟列表。这在很大程度上假设用户不会立即执行需要自动完成的操作,您仍然可以加载页面并允许用户执行其他操作。自动完成列表的加载在大多数情况下应该是无声且无缝的。

这对于少于几秒到几秒的加载时间非常有用,但如果您花费的时间超过此时间,那么您的用户可能仍会遇到可用性问题。

如果仍然存在服务器端延迟,请考虑使用一些时序语句来尝试确定瓶颈在哪里。

【讨论】:

如果你使用这个,你可以用 json_encode 替换你的 foreach 循环。 正是我的想法。做出改变并不难,它会让它看起来更像 Web 2.0 并且可能会更快一点。我还应该补充一点,Afonso 可能需要在返回 JSON 数组之前将 PHP 中的内容类型设置为“application/json”,以便浏览器将其识别为 JSON。 谢谢jmort,我要深入研究一下代码,非常感谢您的建议! 看起来您正在从 memcached 中获取一个数组。 json_encode 应该自动为您将数组编码为 JSON 字符串。因此,您无需将其括在引号中或对其执行任何操作。在 jQuery 回调函数中检索后,您将能够循环通过该数组,但在 javascript 中。查看json_encode 页面以获取示例和用法。你真的很亲密。 这正是我所需要的。非常感谢。

以上是关于加速 jQuery AutoComplete(不可避免的长列表)的主要内容,如果未能解决你的问题,请参考以下文章

Jquery AutoComplete的使用方法实例

jQuery.Autocomplete实现自动完成功能(详解)

jQuery.autoComplete 多参数

JQuery UI之Autocomplete

JQuery UI之Autocomplete

JQuery Autocomplete实战