代码之家  ›  专栏  ›  技术社区  ›  The.Anti.9

优化JS数组搜索

  •  2
  • The.Anti.9  · 技术社区  · 15 年前

    我正在开发一个基于浏览器的媒体播放器,它几乎完全用HTML5和JavaScript编写。后端是用PHP编写的,但它有一个功能,即在初始加载时填充播放列表。剩下的都是JS。有一个搜索栏可以优化播放列表。我希望它能像大多数媒体播放器一样,在用户输入时进行改进。唯一的问题是,这是非常缓慢和滞后,因为有大约1000首歌曲在整个节目,有可能会有更多随着时间的推移。

    最初的播放列表加载是对PHP页面的Ajax调用,该页面将结果作为JSON返回。每件物品有4个阁楼:

    1. 艺术家
    2. 专辑
    3. 文件
    4. 网址

    然后循环遍历每个对象并将其添加到名为 playlist . 在循环结束时 播放列表 被创建, backup . 这是为了让我可以完善 播放列表 当人们改进搜索,但仍然从 备份 无需发出另一个服务器请求。

    方法 refine() 当用户在搜索框中键入键时调用。它冲刷 播放列表 并搜查每一处房产(不包括 url )中的每个对象 备份 字符串中匹配项的数组。如果任何属性中存在匹配项,则它将信息附加到显示播放列表的表中,并将其添加到对象中 播放列表 供实际玩家使用。

    代码 精炼() 方法:

    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 回复  |  直到 15 年前
        1
  •  3
  •   Chetan S    15 年前
    1. $('#search') 不便宜。把它移到圈外。
    2. 移动 append() 在环外。只需将标记累积到字符串中,并在循环后追加一次。

    这个应该快得多

    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();
    }
    
        2
  •  2
  •   Seph    15 年前

    我建议您以不同的方式构建播放列表信息。只需将播放列表信息按第一个字母进行拆分,您就可以获得相当不错的性能提升。

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

    当然,对文件和艺术家也是如此。

        3
  •  1
  •   rg88    15 年前

    您可以做的一件事是利用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');