【问题标题】:Is there a way to load ajax pages without loading http requests on the requested pages?有没有办法加载 ajax 页面而不在请求的页面上加载 http 请求?
【发布时间】:2013-11-20 17:17:38
【问题描述】:

我为游戏编写了一个 javascript/jquery 脚本,我的脚本有可能发出 100 个同步页面请求。我遇到的问题是加载时间太长。我已经诊断出原因是我请求的页面有几个外部图像链接,所以对于我请求的每个页面,该页面都会发出大约 10 个其他请求。我没有办法从页面中删除图像,所以有没有办法让 ajax 请求排除任何外部 http 请求?

这是我发出请求的脚本部分

function getPage(i,pages){
    if(i<pages){
        changeHeader(filter_41 + " " + (i+1) + "/" + pages + " <img src='graphic/throbber.gif' height='24' width='24'></img>");
        var urlParams;

        if(urlParam('t') != 0){
            urlParams = {order: $('#orderBy').val(),dir: $('#direction').val(),screen: "am_farm", Farm_page: i, village: urlParam('village'), t: urlParam('t')};
        }
        else{
            urlParams = {order: $('#orderBy').val(),dir: $('#direction').val(),screen: "am_farm", Farm_page: i, village: urlParam('village')};
        }
        ajaxRequest = $.ajax({
            url: "/game.php",
            type: "GET",
            data: urlParams,
            dataType: "text",
            async: true,
            success: function(){
                setTimeout(function(){getPage(i+1, pages);},1);
            }
        });

        ajaxRequest.done(function(data) {
            // append all table rows retrieved from data except for first two and the last
            $('#am_widget_Farm tr', data).not(":last").slice(2).each(function(){
                $('#am_widget_Farm tr:last').after("<tr>"+$(this).html()+"</tr>");
            });
        });
    }
    else{
        setTimeout(function(){
            addTableInfo();
            applyFilters();
            changeHeader(filter_40);
            highlightRows();
        },1);
        $('#am_widget_Farm').show();
        pagesLoaded = true;
    }
}

【问题讨论】:

    标签: jquery ajax http


    【解决方案1】:

    您只需要检查传入的 HTML 内容并从中获取您想要的任何部分,然后仅将这些内容添加到您的 DOM 中。在您实际尝试将内容添加到 DOM 并呈现之前,您的浏览器不会对传入 HTML 中指定的资源发出任何请求。

    当然,这可能说起来容易做起来难,具体取决于您尝试加载的内容的格式。如果您可以控制正在加载的页面,那么您真正应该做的是修改这些 URL(或创建新的 URL 端点)以仅发送您想要的内容。

    【讨论】:

    • 感谢您的回复,迈克。如果我理解正确,我相信我已经在 ajaxRequest.done() 中这样做了。 “在您实际尝试将该内容添加到 DOM 并呈现之前,您的浏览器不会对传入 HTML 中指定的资源发出任何请求。”不过,这很有帮助。如果它所请求的只是文本,那么该页面的大小会有多大影响。我注意到没有更多内容的页面请求之间存在几秒钟的差异。有没有办法只请求特定元素而不是整个页面然后检索该元素?
    • @ntoombs19 jQUery load() 方法允许您从远程文档中指定要加载到给定本地 DOM 元素中的元素,但这实际上并没有缩短完成所需的时间远程资源上的请求,因为仍然下载整个远程文档并从中解析所需的元素。确实,缩短完成实际 HTTP 响应/请求所需时间的唯一方法是从端点发送更少的内容(即只发送您需要的数据)。
    【解决方案2】:

    ajax 请求返回一个 HTML 字符串。当时没有加载或请求任何图像 - 它只是一串数据。

    当您将该字符串放入 jQuery 对象时,jQuery 通过要求浏览器对其进行解析并将其转换为 DOM 对象,从而将其转换为 DOM 片段。此时,浏览器会解析 HTML 中的 &lt;img&gt; 标签并请求 .src 值(导致您的问题)。

    因此,要解决您的问题,您需要在解析 HTML 之前删除或禁用 &lt;img&gt; 标签。您可能需要将 HTML 作为字符串进行操作,并且必须在将该 HTML 字符串提供给 jQuery 对象之前执行此操作(因为那是它被解析并在您的代码中变成真正的 DOM 元素的时候)。

    我可以想到几种方法来做到这一点:

    1. 您可以创建自己的粗略 HTML 搜索器并从 HTML 字符串中删除任何 &lt;img ...&gt; 标记。

    2. 您可以从 &lt;img&gt; 标记中的 HTML 字符串中删除任何 .src 属性。

    如果这只适用于您可以测试的一些已知内容,而不是网络上的任何可能内容,那么您通常可以采取一些捷径。例如,这是从 HTML 字符串中删除 &lt;img&gt; 标记的简单方法:

    html = html.replace(/<img[^>]+>/gi, "");
    

    或者更简单一点(把 img 标签变成别的东西):

    html = html.replace(/<img/gi, "<ximg");
    

    我并不是说这是 100% 万无一失(可能需要一个真正的 HTML 解析器),但它可能会解决您的问题。

    【讨论】:

    • 添加了用于从 HTML 字符串中查找和删除 &lt;img&gt; 标记的代码示例。
    • 有没有办法为此使用浏览器的 XML 解析器?解析 XML 应该只是将其视为未解释的 DOM 片段,而不应特殊处理 &lt;img&gt; 标签,不是吗?
    • @Barmar - 我不知道如何使用 XML 解析器。