如何在返回响应之前获取 AJAX 获取请求以等待页面呈现?

IT技术 javascript jquery ajax greasemonkey tampermonkey
2021-01-17 03:44:01

我正在为此站点(Site1)中的页面编写 Greasemonkey 脚本Site1 有各种优惠和优惠,我的 GM 脚本旨在执行以下操作:

当访问 Site1 上的报价时,脚本会查询 Site2以查明该酒店是否也列在 Site2 上。如果是,则在 Site1 上显示来自 Site2 的搜索结果。

问题是 Site2 显示一个进度条(“加载结果”),然后显示结果。因此我的 Ajax 请求总是返回空结果,看起来像这样(见红框部分):(
点击查看大图)未完成的结果


但是,它实际上应该包含来自 Site2 的搜索结果的完整内容,如下所示:(
点击查看大图)完成的结果


我尝试了同步 Ajax 请求GM_xmlhttpRequest,但无济于事。

这是站点 2 有问题的进度条:(
点击查看大图)状态栏


在将响应返回给 Site1 之前,如何获取 AJAX 请求以等待 Site2 上的搜索完全呈现?

作为参考,我完整的工作脚本代码位于 pastebin.com

这是相关的片段:

$(document).ready(function(){   
var rewardsSiteResults = $('<div class="panel deal-panel rc-lr"></div>').attr('id', "rewardsSiteResults")
        .html("<p>" + progressMessageText + "</p> ").append(spinnerGif);
$(insertSelector).after(rewardsSiteResults);

var addressMap = getAddressOfHotel();
var pinCode = addressMap[pinCodePlaceHolder];
var hotelName = addressMap[hotelNamePlaceHolder];
var queryURL = constructQueryURL(pinCode, hotelName);

$.ajaxSetup({async:true, timeout: 5000});
$.get(queryURL,null, function(response) {
    if(!displayed){
        displayed=true;
        //rewardsSiteResults.html("adfaasddsf");
        var text = $(response).find("#col2");
        $(text).find("script").remove();

        //console.log(text.html())
//          $('<iframe id="someId"/>').appendTo('#rewardsSiteResults')
//          .contents().find('body').append(response);
        rewardsSiteResults.html("<div class='panel deal-panel rc-lr'>" + text.html() +"</div>");
        //console.log(response);
    }
},'html');  
});
1个回答

为了让 AJAX 能够“等待页面呈现”,它实际上必须完全处理页面,获取并运行所有包含的 CSS 和 javascript 文件。这并不容易,也不推荐。幸运的是,无论如何您都不需要这样做。

以下是解决此类问题的三种更好方法:

  1. 资源页面(mpdining.rewardsnetwork.com,对于这个问题),可能有一个API。如果有,找到它并使用它。如果可以,这是您最好的选择。

  2. 分析资源页面的 javascript 和/或 AJAX 请求。使用GM_xmlhttpRequest()直接取刚刚有效载荷数据,而不是试图解析资源页面。

    有时此过程相当简单,但某些站点需要复杂的交互和/或身份验证。

  3. 在隐藏的 iframe 中加载资源页面;将您的 Greasemonkey 脚本设置为在资源页面和母版页面上运行,并使用postMessage().

    这种方法几乎总是有效,尽管您可能必须防止某些页面试图“退出”iframe。



使用隐藏的 iframe 从跨域资源页面获取数据:

Greasemonkey 脚本将在普通页面和 iframe 内的页面上运行。事实上,您可以将相同的脚本设置为在两个域和多个域上运行。

如果母版页和 iframe资源页都运行 GM 脚本,则脚本实例可以使用postMessage().

例如,假设我们有一个网站,fiddle.jshell.net/9ttvF/show,包含旅游数据,我们要混搭了该网站与从匹配数据资源网站jsbin.com/ahacab,使用AJAX获取其有效载荷数据。

目标(主)站点如下所示:
目标站点

资源站点起初看起来像这样:
资源站点,开始

然后像这样结束: 资源站点,完成


以下脚本:

  1. 在隐藏的 iframe 中加载资源页面。
  2. 启动在 iframe 页面上运行的第二个实例。
  3. 等待 iframe 页面完成,根据需要处理结果。
  4. 将所需的有效负载数据发送到在目标(母版)页面上运行的 GM 脚本。
  5. 目标页面的脚本然后插入有效负载数据以完成混搭。
// ==UserScript==
// @name     _Cross-site, AJAX scrape demo
// @include  http://fiddle.jshell.net/9ttvF/show/
// @include  http://jsbin.com/ahacab*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==

if (/fiddle\.jshell\.net/i.test (location.host) ) {
    console.log ("***Master-page start...");

    /*--- Inform the user.
    */
    $("#plainResults").before (
        '<div id="gmFetchRez">Greasemonkey is fetching results from jsbin.com...</div>'
    );

    /*--- Setup to process messages from the GM instance running on the iFrame:
    */
    window.addEventListener ("message", receiveMessage, false);

    /*--- Load the resource site in a hidden iframe.
    */
    $("body").append ('<iframe src="http://jsbin.com/ahacab" id="gmIframe"></iframe>');
}
else {
    console.log ("***Framed start...");
    /*--- Wait for the AJAXed-in content...
    */
    waitForKeyElements ("#results table.rezTable", sendResourcePageData);
}

function sendResourcePageData (jNode) {
    console.log ("Results found!  Sending them to the main window...");

    window.top.postMessage (jNode.html(), "*");
}

function receiveMessage (event) {
    if (event.origin != "http://jsbin.com")     return;

    $("#gmFetchRez").html (event.data);
}

//--- Use CSS to control appearances.
GM_addStyle ( "                                 \
    #gmIframe {                                 \
        display:            none;               \
    }                                           \
    #gmFetchRez {                               \
        background:         lightYellow;        \
        border:             3px double red;     \
        padding:            1em;                \
    }                                           \
" );

安装并运行脚本后,最终结果如下所示: 混搭结果

布洛克,它起作用了!!!!:) 非常感谢 !!我会稍微清理一下我的脚本然后发布它以便其他人可以参考它!干杯!
2021-04-01 03:44:01
布洛克 .. 在我说什么之前.. 请让我这样说.. 这是纯粹的、未经稀释的令人敬畏.. 我感谢你提供的精致细节。太感谢了。我没有提到我第二个站点没有 API,我花了几个小时试图在 Firebug 的帮助下理解它的资源请求,但无济于事。后者因第二个站点使用 DWR 的事实而变得复杂。我对第三种选择感到非常兴奋,会尽快报告。感谢您抽出宝贵时间撰写如此出色的解释。
2021-04-10 03:44:01