Я использую CasperJS для автоматизации серии кликов, заполненных форм, анализа данных и т. Д. Через веб-сайт.
Кажется, что Casper организован в список предустановленных шагов в форме then
операторов (см. Их пример здесь: http://casperjs.org/quickstart.html ), но неясно, что запускает следующий оператор на самом деле.
Например, then
ожидает ли завершения всех ожидающих запросов? Считается ли injectJS
ожидающим запросом? Что произойдет, если у меня есть then
инструкция, вложенная в конец open
инструкции?
casper.thenOpen('http://example.com/list', function(){
casper.page.injectJs('/libs/jquery.js');
casper.evaluate(function(){
var id = jQuery("span:contains('"+itemName+"')").closest("tr").find("input:first").val();
casper.open("http://example.com/show/"+id); //what if 'then' was added here?
});
});
casper.then(function(){
//parse the 'show' page
});
Я ищу техническое объяснение того, как поток работает в CasperJS. Моя конкретная проблема в том, что мое последнее then
утверждение (выше) выполняется перед моим casper.open
утверждением, и я не знаю почему.
javascript
casperjs
Bendytree
источник
источник
flow
принципов casperjs, но обнаружил, что вы не можете ссылаться на casper изevaluate
вызова. (т.е. вы не можете открыть новый URL, журнал, эхо и т. д.). Итак, в моем случае была вызвана оценка, но без возможности взаимодействия с внешним миром.evaluate()
предназначен для кода, который выполняется в «браузере», в DOM страницы, которую просматривает phantomjs. Так что там нетcasper.open
, но может быть jQuery. Итак, ваш пример не имеет смысла, но мне все еще интересно, что наthen()
самом деле.Ответы:
then()
в основном добавляет новый шаг навигации в стек. Шаг - это функция javascript, которая может делать две разные вещи:Возьмем простой сценарий навигации:
Вы можете распечатать все созданные шаги в стеке следующим образом:
Это дает:
Обратите внимание на
_step()
функцию, которая была автоматически добавлена CasperJS для загрузки URL-адреса для нас; когда URL-адрес загружен, вызывается следующий шаг, доступный в стекеstep3()
.Когда вы определили шаги навигации,
run()
выполняйте их один за другим последовательно:Сноска: материал обратного вызова / слушателя - это реализация шаблона обещания .
источник
then()
просто регистрирует серию шагов.run()
и его семейство функций-исполнителей, обратных вызовов и слушателей - это все, что на самом деле выполняет работу по выполнению каждого шага.Всякий раз , когда шаг завершен, CasperJS будет проверять против 3 флагов:
pendingWait
,loadInProgress
, иnavigationRequested
. Если какой-либо из этих флагов истинен, ничего не делайте, переходите в режим ожидания до более позднего времени (setInterval
стиль). Если ни один из этих флагов не истинен, будет выполнен следующий шаг.Что касается CasperJS 1.0.0-RC4, существует ошибка, при которой при определенных обстоятельствах, зависящих от времени, метод «попытаться выполнить следующий шаг» будет срабатывать до того, как CasperJS успеет поднять один из флагов
loadInProgress
илиnavigationRequested
. Решение состоит в том, чтобы поднять один из этих флагов перед тем, как выйти из любого шага, на котором эти флаги должны быть подняты (например: поднять флаг до или после запроса acasper.click()
), может быть так:(Примечание: это только иллюстрация, больше похоже на псевдокод, чем на правильную форму CasperJS ...)
Чтобы обернуть это решение в одну строку кода, я представил
blockStep()
в этом запросе на перенос на github расширениеclick()
иclickLabel()
как средство, помогающее гарантировать получение ожидаемого поведения при использованииthen()
. Ознакомьтесь с запросом для получения дополнительной информации, шаблонов использования и минимального количества тестовых файлов.источник
blockStep
, ИМХОСогласно документации CasperJS :
then()
Подпись:
then(Function then)
За кулисами, исходный код
Casper.prototype.then
приведен ниже:Пояснение:
Другими словами,
then()
планирует следующий шаг в процессе навигации.Когда
then()
вызывается, ему передается функция как параметр, который должен вызываться как шаг.Он проверяет, запущен ли экземпляр, и, если нет, отображает следующую ошибку:
Затем он проверяет, есть ли
page
объектnull
.Если условие истинно, Каспер создает новый
page
объект.После этого
then()
проверяетstep
параметр, чтобы проверить, не является ли он функцией.Если параметр не является функцией, отображается следующая ошибка:
Затем функция проверяет, запущен ли Каспер.
Если Каспер не запущен,
then()
добавляет шаг в конец очереди.В противном случае, если Casper запущен, он вставляет подшаг на уровень глубже, чем предыдущий.
Наконец,
then()
функция завершается генерациейstep.added
события и возвращает объект Casper.источник