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

时间:2012-07-14 18:24:05

标签: javascript ajax jquery greasemonkey

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

当访问Site1上的商品时,脚本会查询Site2以确定该商店是否也列在Site2上。如果是这样,请在Site1上显示Site2的搜索结果。

问题是Site2显示进度条(“加载结果”),然后显示结果。因此,我的Ajax请求总是返回空结果,看起来像这样(参见红框部分):
(Click for larger image)unfinished results


但是,它实际上应该具有Site2搜索结果的完整内容,如下所示:
(Click for larger image)finished results


我尝试过同步Ajax请求以及GM_xmlhttpRequest无效。

这是站点2的问题进度条:
(Click for larger image)status bar


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

供参考,my complete working script code is at 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 个答案:

答案 0 :(得分:9)

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

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

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

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

    有时这个过程相当容易,但有些网站需要复杂的交互和/或身份验证。

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

    这种方法几乎总能奏效,但您可能不得不阻止某些网页尝试“淘汰”iframe。



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

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

    如果 母版页 和iframed 资源页 都在运行GM脚本,脚本实例可以使用postMessage()进行跨域通信。

    例如,假设我们有一个包含旅行数据的网站fiddle.jshell.net/9ttvF/show,我们希望 mash-up 该网站包含匹配的数据 资源网站 jsbin.com/ahacab,使用AJAX获取其有效负载数据。

    The target (master) site看起来像这样:
    target site

    The resource site起初看起来像这样:
    resource site, start

    然后这样结束: resource site, finish


    以下脚本:

    1. 在隐藏的iframe中加载资源页面。
    2. 启动在iframed页面上运行的第二个实例。
    3. 等待iframed页面完成,根据需要处理结果。
    4. 将所需的有效负载数据发送到目标(主)页面上运行的GM脚本。
    5. 目标页面的脚本然后插入有效负载数据以完成混搭。
    6. // ==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;                \
          }                                           \
      " );
      

      最终结果如下所示,脚本已安装并运行: mashup result