PhantomJS - метод WaitFor не будет выполнять функцию. Программа застряла
У меня возникли некоторые проблемы с использованием waitFor-метода в PhantomJS.
Вот что я хочу сделать:
- Загрузка нескольких веб-страниц по сгенерированным URL
- Используйте jQuery для анализа некоторых ссылок с этих страниц.
- Сохраните каждую проанализированную ссылку в одном массиве (в этом примере я просто зарегистрирую их)
Я использую метод waitFor (), так что я могу ждать, пока страница не будет оценена. Как я понимаю, этот метод не позволит программе продолжаться до тех пор, пока функция, которую я передаю в качестве параметра, не выдаст ничего.
Моя проблема: На самом деле программа не будет продолжать работать после выполнения waitFor-Method. Это просто застряло. Там нет никакой ошибки вообще. Функция, которую я передал в качестве параметра, не будет выполнена... по крайней мере, в консоли нет регистрации.
Когда я удаляю waitFor-Methot, он будет правильно выполнять код, однако я не могу выполнить метод handleSeriesPageListPage ()- несколько раз. Я действительно не слишком увлекаюсь js и callbacks или асинхронной обработкой методов. Я думаю, что я сделал несколько серьезных ошибок, и некоторые эксперты по javascript смогут мне быстро помочь:).
"use strict";
var page = require('webpage').create();
page.onConsoleMessage = function (msg) {
console.log(msg);
};
var seriesPageBaseUrl = "https://www.example.com?pageid=";
var simpleBaseUrl = "https://www.example.com/";
var seriesPageIds = [0xx, 1xx];
var allSeriesUrls = [];
function handleSeriesPageListPage(url) {
console.log("Open url: " + url);
page.open(url, function (status) {
console.log("status: " + status);
if (status === "success") {
waitFor(
function () {
return page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {
console.log("Included JS");
return page.evaluate(function () {
console.log("evaluate result...");
$('.list_item').each(function () {
var seriesLink = jQuery(this).find("a").first().attr("href");
var seriesUrl = simpleBaseUrl + seriesLink;
console.log(seriesUrl);
return true;
});
});
});
}
);
} else {
phantom.exit(1);
}
});
}
function nextSeriesListPage() {
var seriesPageId = seriesPageIds.shift();
if (typeof seriesPageId === "undefined") {
console.log(allSeriesUrls);
phantom.exit(0);
}
var targetURL = seriesPageBaseUrl + seriesPageId;
handleSeriesPageListPage(targetURL);
}
nextSeriesListPage();
1 ответ
waitFor()
Используемая вами функция не подходит для обработки асинхронных задач, и вы на самом деле неправильно поняли, что она делает:
waitFor(testFx, onReady, timeOutMillis)
принимает три параметра (третий необязательный). Первый параметр - это тестовая функция. Он выполняется многократно, но каждый раз синхронно, пока его возвращаемое значение не будет true
, Затем выполняется функция, заданная в качестве второго параметра. Если в течение периода, заданного третьим параметром (или 3 секунды по умолчанию), нет true
значение возвращается, функция завершается с сообщением журнала 'waitFor()' timeout
,
Вы предоставили только один параметр; функция, которая завершается без возвращаемого значения (page.includeJs()
, в принципе). Соответственно, waitFor()
должен выйти через 3 секунды с timeout
сообщение.
То, чего вы действительно хотели достичь, было
- дождитесь загрузки страницы
- затем вставьте скрипт jQuery и дождитесь этого,
- затем переоценить, и ждать этого,
- затем извлекать информацию
Это четыре асинхронных задачи. Основной подход, предписанный PhantomJS, состоит в том, чтобы перейти к соответствующему следующему шагу внутри предыдущей функции обратного вызова, что приводит к четырем вложенным обратным вызовам.
Поскольку это не очень хороший шаблон (его обычно называют адом обратного вызова), шаблон Promise был представлен как функция Javascript (или включен в несколько библиотек).
Чтобы узнать, как переформулировать API обратного вызова в качестве Promises, взгляните на Как преобразовать существующий API обратного вызова в обещания?