如何获得一个AJAX获取请求等待页面被渲染之前返回一个响应?

我正在为本网站 (Site1)中的页面编写Greasemonkey脚本。 Site1有各种交易和提供,我的GM脚本旨在做到以下几点:

当访问Site1上的一个报价时,该脚本查询Site2以确定该酒店是否也在Site2上列出。 如果是这样,则在Site1上显示来自Site2的search结果。

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

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

我尝试了同步Ajax请求以及GM_xmlhttpRequest无济于事。

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

我怎样才能得到的AJAX请求等待Site2上的search完全呈现之前,返回到Site1的响应?

作为参考, 我的完整工作脚本代码位于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'); }); 

为了AJAX得到“等待页面呈现”,它实际上必须完全处理页面,获取并运行所有包含的CSS和JavaScript文件。 这并不容易,也不推荐。 幸运的是,你不需要那样做。

这里有三种更好的方法来处理这种问题:

  1. 资源页面 (mpdining.rewardsnetwork.com,对于这个问题)可能有一个API。 如果有,find并使用它。 这是你最好的select,如果有的话。

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

    有时候这个过程相当简单,但有些网站需要复杂的交互和/或authentication。

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

    这种方法几乎总是有效的,尽pipe你可能不得不阻止一些页面试图“去除”iframe。


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

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

如果一个主页面和一个iframed 资源页面都运行GM脚本,那么这个脚本实例可以使用postMessage()与其他域进行交互。

例如,假设我们有一个包含旅游数据的网站fiddle.jshell.net/9ttvF/show ,并且我们希望将该网站与来自资源网站 jsbin.com/ahacab的匹配数据进行混搭,该网站使用AJAX获取其有效载荷数据。

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

资源网站首先是这样的:
资源网站,启动

然后完成这样的: 资源网站,完成

以下脚本:

  1. 在隐藏的iframe中加载资源页面。
  2. 启动在iframed页面上运行的第二个自己的实例。
  3. 等待iframed页面完成,根据需要处理结果。
  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; \ } \ " ); 

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