如何获得一个AJAX获得请求等待页面返回响应之前要呈现? [英] How to get an AJAX get-request to wait for the page to be rendered before returning a response?

查看:208
本文介绍了如何获得一个AJAX获得请求等待页面返回响应之前要呈现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在写的Greasemonkey脚本在<一个网页的过程href="http://www.livingsocial.com/cities/368-albany-capital-region/deals/382236-20-to-spend-on-food-and-drink"相对=nofollow>这个网站(站点1)。站点1拥有交易和各种优惠和我的GM脚本的目标是做到以下几点:

当人访问任何要约站点1时,脚本查询站点2 找出这家酒店是否也列在站点2。如果是的话,显示来自Site2的搜索结果中的站点1。

问题是,站点2显示一个进度条(装载结果),然后显示结果。因此,我的Ajax请求总是返回空的结果看起来是这样的(见红色盒装部分):
(点击查看大图)


但是,它实际上应该是具有从Site2的搜索结果的完整内容,就像这样:
(点击查看大图)


我已经尝试了同步Ajax请求以及 GM_xmlhtt prequest 无济于事。

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


我怎样才能获得AJAX请求等待在Site2内被搜索到返回响应到站点1之前完全呈现?

有关参考,我的完整工作脚本code是在pastebin.com

这是有关的片段:

  $(文件)。就绪(函数(){
VAR rewardsSiteResults = $('&LT; D​​IV CLASS =面板处理面板RC-LR&GT;&LT; / DIV&GT;')。ATTR('身份证',rewardsSiteResults)
        html的(&其中; P&gt;中+ progressMessageText +&所述; / P&gt;中).append(spinnerGif);
$(insertSelector)。之后(rewardsSiteResults);

变种addressMap = getAddressOfHotel();
VAR针code = addressMap [引脚codePlaceHolder]。
VAR酒店名称= addressMap [hotelNamePlaceHolder]
VAR queryURL = constructQueryURL(引脚code,酒店名称);

$ .ajaxSetup({异步:真,超时:5000});
$获得(queryURL,空,函数(响应){
    如果(!显示){
        显示= TRUE;
        //rewardsSiteResults.html("adfaasddsf);
        变种文本= $(响应).find(#COL2);
        $(文字).find(脚本),删除()。

        //console.log(text.html())
// $('&LT; IFRAME ID =someId/&GT;')appendTo('#rewardsSiteResults)。
// .contents()找到(身体)追加(响应)。
        rewardsSiteResults.html(&LT; D​​IV CLASS ='面板处理面板RC-LR&gt;中+ text.html()+&LT; / DIV&gt;中);
        //console.log(response);
    }
},HTML);
});
 

解决方案

为了使AJAX到等待页面被渲染,它实际上要完全处理的页面,获取的和运行的所有包含CSS和JavaScript文件。这并不容易,不建议使用。幸运的是,你并不需要做的反正。

下面三种更好的方法来处理这​​一类问题:

  1. 资源页(mpdining.rewardsnetwork.com,对于这个问题),可能有一个API。如果这样做,发现它与使用它。这是你最好的选择,如果它是可用的。

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

    有时候,这个过程是相当容易的,但有些网站需要复杂的相互作用和/或认证。

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

    这个方法几乎总是工作,虽然你可能需要prevent一些网页,从尝试的iframe到萧条出来。



使用一个隐藏的iframe来从跨域数据,资源页面:

Greasemonkey脚本将运行在这两个普通页面和内置页框内页。事实上,你可以设置相同的脚本在两个运行,并且在多个领域。

如果一个 母版页和iframed的资源页都运行通用脚本(s)时,脚本实例可以相互搭配,跨域通信,使用 的postMessage( )

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

目标(主)网站看起来是这样的:

资源网站看起来像这样在第一次:

然后完成这样的:


下面的脚本:

  1. 加载资源页面中隐藏的iframe。
  2. 开始的iframed页上运行自身,第二个实例。
  3. 等待iframed页面完成,处理结果根据需要。
  4. 发送所需的有效载荷数据到目标(主)页面上运行的通用脚本。
  5. 目标页的脚本然后插入有效载荷数据来完成的混搭。

// == UserScript == // @name _Cross现场,AJAX刮演示 // @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 == 如果(/fiddle\.jshell\.net/i.test(location.host)){     的console.log(***母版页开始......);     / * ---通知用户。     * /     $(#plainResults)。前(         '&LT; D​​IV ID =gmFetchRez&GT;的Greasemonkey是从获取结果jsbin.com ...&LT; / DIV&GT;     );     / * ---设置来处理来自对iFrame的运行GM实例的消息:     * /     window.addEventListener(信息,receiveMessage,假);     / * ---加载资源网站中隐藏的iframe。     * /     $(机构)追加('&LT; IFRAME SRC =htt​​p://jsbin.com/ahacabID =gmIframe&GT;&LT; / IFRAME&GT;'); } 其他 {     的console.log(***陷害开始......);     / * ---等待AJAX​​ed-内容...     * /     waitForKeyElements(#results table.rezTable,sendResourcePageData); } 功能sendResourcePageData(jNode){     的console.log(结果发现它们发送到主窗口......!);     window.top.postMessage(jNode.html(),*); } 功能receiveMessage(事件){     如果(event.origin =htt​​p://jsbin.com!)回报;     $(#gmFetchRez)HTML(event.data)。 } // ---用CSS来控制露面。 GM_addStyle(\     #gmIframe {\         显示:无; \     } \     #gmFetchRez {\         背景:浅黄; \         边框:3PX双红; \         填充:1EM; \     } \ );


最后的结果是这样的,安装脚本并运行:

I am in the process of writing a Greasemonkey Script for pages in this site (Site1). Site1 has deals and offers of various kinds and my GM script aims to do the following:

When one visits an offer on Site1, the script queries Site2 to find out whether this hotel is also listed on Site2. If so, display the search results from Site2 on Site1.

The problem is that Site2 displays a progress bar ("Loading Results") and then displays the results. Thus my Ajax request always returns empty results and looks like this (See the red-boxed portion):


However, it should actually have the complete contents of the search results from Site2, like so:


I have tried a synchronous Ajax request as well as GM_xmlhttpRequest to no avail.

This is the problematic progress bar of Site 2:


How can I get the AJAX request to wait for the the search on Site2 to be completely rendered before returning the response to Site1?

For reference, my complete working script code is at pastebin.com.

This is the relevant snippet:

$(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');  
});

解决方案

In order for the AJAX get to "wait for the page to be rendered", it would actually have to fully process the page, fetching and running all the included CSS and javascript files. That's not easy and not recommended. Fortunately, you don't need to do that anyway.

Here are three better ways to approach this kind of problem:

  1. The resource page (mpdining.rewardsnetwork.com, for this question) might have an API. If it does, find it and use it. This is your best bet, if it's available.

  2. Analyze the resource page's javascript and/or AJAX requests. Use GM_xmlhttpRequest() to directly fetch just the payload data, instead of trying to parse the resource page.

    Sometimes this process is fairly easy, but some sites require complex interaction and/or authentication.

  3. Load the resource page in a hidden iframe; set your Greasemonkey script to run on both the resource page and the master page and to relay the desired data using postMessage().

    This approach will almost always work, although you may have to prevent some pages from attempting to "bust out" of the iframe.



Using a hidden iframe to get data from a cross-domain, resource page:

Greasemonkey scripts will run on both a normal page and on pages within iframes. In fact, you can set the same script to run on both, and on multiple domains.

If a master page and an iframed resource page are both running GM script(s), the script instances can communicate with each other, cross-domain, using postMessage().

For example, suppose we have a site, fiddle.jshell.net/9ttvF/show, that contains travel data, and we want to mash-up that site with matching data from a resource site, jsbin.com/ahacab, that uses AJAX to get its payload data.

The target (master) site looks like this:

The resource site looks like this at first:

Then finishes like this:


The following script:

  1. Loads the resource page in a hidden iframe.
  2. Starts a second instance of itself running on the iframed page.
  3. Waits for the iframed page to finish, processing the results as desired.
  4. Sends the desired payload data to the GM script running on the target (master) page.
  5. The target-page's script then inserts the payload data to complete the mash-up.

// ==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;                \
    }                                           \
" );


The final result looks like this, with the script installed and running:

这篇关于如何获得一个AJAX获得请求等待页面返回响应之前要呈现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆