setInterval и this.wait в casper.js

Мне нужно сделать цикл 3 раза по 2 секунды между каждой итерацией. Я пробовал эти 3 варианта:

Вариант 1

var casper = require('casper').create({
    verbose: false,
    logLevel: 'debug'
});

casper.start("http://google.com");

casper.on('remote.message', function(msg) {
    this.echo('remote message caught: ' + msg);
})

casper.thenEvaluate(function() {
    var x = 0;
    var intervalID = setInterval(function () {

       console.log("Using setInternal " + x);

       if (++x === 3) {
           window.clearInterval(intervalID);
       }
    }, 2000);

});

casper.run();

Наблюдение: ничего не появилось, потому что сценарий завершился сразу перед вызовом первого setInterval.

Вариант 2

Заменено thenEvaluate() на then() ниже

for (i=0; i<3; i++) {
    this.wait(2000);
    this.echo('Using this.wait ' + i);
}

Наблюдение: он выводит 3 раза сразу, а затем долго ждет, так как this.wait() является асинхронным. Это не то, чего я хочу, потому что мне нужна задержка между ними.

Вариант 3. Замените часть в then() приведенной ниже. Я думал о рекурсивном вызове waitFunc() после каждого вызова wait().

var count = 0;
var waitFunc = function() {
    this.wait(2000, function() {
        if (count < 3) {
            casper.echo('Using this.wait ' + count);
            count++;
            waitFunc();
        }
    });

};

Наблюдение: на экране ничего не выводится.

Итак, мой вопрос: Как заставить this.wait или setInterval работать в цикле 3 раза, как в этом случае?


person HP.    schedule 25.11.2012    source источник
comment
Я попробовал все 3 варианта, и ни один не работал   -  person HP.    schedule 26.11.2012


Ответы (1)


Вот пример реализации для решения вашей проблемы:

var casper = require('casper').create();
var last, list = [0, 1, 2, 3];

casper.start("http://google.fr/", function() {
    this.echo('google');
});

casper.on('remote.message', function(msg) {
    this.echo('remote message caught: ' + msg);
});

casper.thenEvaluate(function() {
    window.x = 0;
    var intervalID = setInterval(function() {
       console.log("Using setInternal " + window.x);
       if (++window.x === 3) {
           window.clearInterval(intervalID);
       }
    }, 500);
});

casper.each(list, function(self, i) {
    self.wait(500, function() {
        last = i;
        this.echo('Using this.wait ' + i);
    });
});

casper.waitFor(function() {
    return last === list[list.length - 1] && 3 === this.getGlobal('x');
}, function() {
    this.echo('All done.').exit();
});

casper.run(function() {});

Пример вывода:

$ casperjs test.js
google
remote message caught: Using setInternal 0
Using this.wait 0
remote message caught: Using setInternal 1
Using this.wait 1
remote message caught: Using setInternal 2
Using this.wait 2
Using this.wait 3
All done.
$
person NiKo    schedule 26.11.2012
comment
Оно работает. Но можете ли вы объяснить использование casper.each вместо цикла for? Почему self.wait() работает в этом случае. Использование цикла for выполнит все this.echo(), а затем долгое ожидание. - person HP.; 28.11.2012
comment
Это из-за того, как работает область видимости javascript. В стандартном цикле for всегда будет установлено самое последнее значение i, поэтому обычно приходится использовать IIFE (Casper.each замыкает цикл внутри IIFE). - person NiKo; 28.11.2012
comment
Ах, судя по ссылке, это тоже работает: casper.then(function() { for (i=0; i‹=3; i++) { this.wait(2000, (function(j) { return function() { this.echo('Тест' + j); }; })(i)); } }); - person HP.; 29.11.2012
comment
Да, конечно, как я уже сказал, Casper.each() просто использует IIFE внутри :) - person NiKo; 29.11.2012