Как получить AJAX-запрос на ожидание отображения страницы перед возвратом ответа?
Я нахожусь в процессе написания скрипта Greasemonkey для страниц на этом сайте (Site1). У Site1 есть предложения и предложения различного рода, и мой сценарий GM стремится сделать следующее:
Когда кто-то посещает предложение на Сайте 1, сценарий запрашивает Сайт 2, чтобы выяснить, указан ли этот отель на Сайте 2. Если это так, отобразите результаты поиска с сайта 2 на сайте 1.
Проблема в том, что Site2 отображает индикатор выполнения ("Загрузка результатов"), а затем отображает результаты. Таким образом, мой Ajax-запрос всегда возвращает пустые результаты и выглядит следующим образом (см. Раздел в красной рамке):
(Нажмите для увеличения изображения)
Однако на самом деле он должен иметь полное содержание результатов поиска с Site2, например:
(Нажмите для увеличения изображения)
Я пробовал синхронный запрос Ajax, а также GM_xmlhttpRequest
но безрезультатно.
Это проблемный индикатор выполнения на сайте 2:
(Нажмите для увеличения изображения)
Как я могу получить AJAX-запрос, чтобы дождаться, пока поиск на Site2 будет полностью обработан, прежде чем возвращать ответ на 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');
});
1 ответ
Для того, чтобы AJAX мог "подождать, пока страница будет отрисована", ему фактически придется полностью обработать страницу, извлечь и запустить все включенные файлы CSS и javascript. Это не легко и не рекомендуется. К счастью, вам все равно не нужно этого делать.
Вот три лучших способа решения этой проблемы:
Страница ресурса (mpdining.rewardsnetwork.com, для этого вопроса) может иметь API. Если это так, найдите его и используйте. Это ваша лучшая ставка, если она доступна.
Проанализируйте javascript и / или AJAX-запросы страницы ресурса. использование
GM_xmlhttpRequest()
напрямую получать только данные полезной нагрузки, вместо того, чтобы пытаться проанализировать страницу ресурса.Иногда этот процесс довольно прост, но некоторые сайты требуют сложного взаимодействия и / или аутентификации.
Загрузите страницу ресурса в скрытый iframe; настройте сценарий Greasemonkey для запуска как на странице ресурсов, так и на главной странице, а также для передачи нужных данных с помощью
postMessage()
,Этот подход почти всегда работает, хотя вам, возможно, придется помешать некоторым страницам попытаться "вырваться" из iframe.
Использование скрытого фрейма для получения данных из междоменной страницы ресурсов:
Скрипты Greasemonkey будут запускаться как на обычной странице, так и на страницах внутри фреймов. Фактически, вы можете установить один и тот же скрипт для запуска как на нескольких доменах, так и на нескольких.
Если на главной странице и на странице ресурса iframed выполняются сценарии GM, экземпляры сценариев могут связываться друг с другом через междоменный домен, используя postMessage()
,
Например, предположим, что у нас есть сайт http://fiddle.jshell.net/9ttvF/show/, который содержит данные о поездках, и мы хотим объединить этот сайт с соответствующими данными с ресурса сайта http://jsbin.com/ahacab, который использует AJAX чтобы получить данные полезной нагрузки.
Целевой (основной) сайт выглядит так:
Ресурс сайта на первый взгляд выглядит так:
Затем заканчивается так:
Следующий скрипт:
- Загружает страницу ресурса в скрытом фрейме.
- Запускает второй экземпляр на странице iframed.
- Ожидание завершения страницы iframed, обработка результатов по желанию.
- Отправляет нужные данные полезной нагрузки в сценарий GM, выполняющийся на целевой (главной) странице.
- Затем скрипт целевой страницы вставляет данные полезной нагрузки для завершения смешивания.
// ==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; \
} \
" );
Окончательный результат выглядит следующим образом: скрипт установлен и запущен: