优化JS阵列搜索

时间:2010-03-19 04:03:34

标签: javascript optimization

我正在开发基于浏览器的媒体播放器,它几乎完全用HTML 5和JavaScript编写。后端是用PHP编写的,但它有一个函数可以在初始加载时填充播放列表。其余的都是JS。有一个搜索栏可以优化播放列表。我希望它能够像大多数媒体播放器那样改进。唯一的问题是它非常慢而且滞后,因为整个节目中有大约1000首歌曲,并且随着时间的推移可能会有更多的歌曲。

原始播放列表加载是对PHP页面的ajax调用,该页面将结果作为JSON返回。每个项目有4个attirbutes:

  1. 艺术家
  2. 专辑
  3. 文件
  4. URL
  5. 然后我遍历每个对象并将其添加到名为playlist的数组中。在循环结束时,会创建playlist的副本backup。这样我可以在人们优化搜索时优化playlist变量,但仍然可以从backup重新填充它,而无需再提出其他服务器请求。

    当用户在搜索框中键入密钥时,会调用方法refine()。它会刷新playlist并搜索url数组中每个对象的每个属性(不包括backup)以查找字符串中的匹配项。如果任何属性中存在匹配项,它会将信息附加到显示播放列表的表中,并将其添加到对象playlist以供实际播放器访问。

    refine()方法的代码:

    function refine() {
        $('#loadinggif').show();
        $('#library').html("<table id='libtable'><tr><th>Artist</th><th>Album</th><th>File</th><th>&nbsp;</th></tr></table>");
        playlist = [];
        for (var j = 0; j < backup.length; j++) {
            var sfile = new String(backup[j].file);
            var salbum = new String(backup[j].album);
            var sartist = new String(backup[j].artist);
            if (sfile.toLowerCase().search($('#search').val().toLowerCase()) !== -1 || salbum.toLowerCase().search($('#search').val().toLowerCase()) !== -1 || sartist.toLowerCase().search($('#search').val().toLowerCase()) !== -1) {
                playlist.push(backup[j]);
                num = playlist.length-1;
                $("<tr></tr>").html("<td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td>").appendTo('#libtable');
            }
        }
        $('#loadinggif').hide();
    }
    

    正如我之前所说,对于输入的前几个字母,这是非常缓慢和滞后的。我正在寻找方法来改进它,使其更快更顺畅。

3 个答案:

答案 0 :(得分:3)

  1. $('#search')并不便宜。将它移到循环外面。
  2. append()移到循环之外。只需在字符串中累积标记,然后在循环后追加一次。
  3. 这应该快得多

    function refine() {
        $('#loadinggif').show();
        $('#library').html("<table id='libtable'><tr><th>Artist</th><th>Album</th><th>File</th><th>&nbsp;</th></tr></table>");
        playlist = [];
        var srchText = $('#search').val().toLowerCase();
        var markup = ["<tbody>"];
        for (var j = 0; j < backup.length; j++) {
            var sfile = backup[j].file.toLowerCase();
            var salbum = backup[j].album.toLowerCase();
            var sartist = backup[j].artist.toLowerCase();
    
            if (sfile.search(srchText) !== -1 || salbum.search(srchText) !== -1 || sartist.search(srchText) !== -1) {
                playlist.push(backup[j]);
                num = playlist.length-1;
                markup.push("<tr><td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td></tr>");
            }
       }   
       markup.push("</tbody>");
       $("#libtable").append(markup.join(''));
       $('#loadinggif').hide();
    }
    

答案 1 :(得分:2)

我建议您稍微改变一下您的播放列表信息。只需将第一个字母拆分播放列表信息,就可以获得相当不错的性能提升。

albums = {
    'a': [list of albums starting with a],
    'b': ...
}

当然,为文件和艺术家做同样的事情。

答案 2 :(得分:1)

你可以做的一件事就是利用jQuery缓存文档片段的能力(这个例子来自John Resig给出的一个话题,但你可以将它应用到你的代码中):

// SLOW AS IT IS NOT CACHED. BECAUSE OF FOO
$("ul").append("<li><a>" + foo + "</a></li>");

// FAST. DOCUMENT FRAGMENT IS CACHED
$("<li><a></a></li>")
    .find("a").text(foo).end()
    .appendTo("ul");

这适用于您的上述行:

$("<tr></tr>").html("<td>" + num + "</td><td>" + sartist + "</td><td>" + salbum + "</td><td>" + sfile + "</td><td><a href='#' onclick='setplay(" + num +");'>Play</a></td>").appendTo('#libtable');