Búsqueda de sitios web

javascript - Sentencias condicionales en CasperJS


Acabo de usar CasperJS para mi proyecto. Su gramática es clara y fácil de aprender. Pero al revisar su documentación, nunca encontré nada sobre declaraciones condicionales. Por ejemplo, podría ser útil si pudiéramos usar CasperJS de la siguiente manera:

var casper = require('casper').create();
var no_error = false;

casper.start('http://casperjs.org/', function() {
    this.echo(this.getTitle());
    no_error = true;
});

if (no_error) {
    casper.thenOpen('http://phantomjs.org', function() {
        this.echo(this.getTitle());
    });
}

casper.run();

¿Hay alguna manera de personalizar CasperJS para que funcione así?

Respuesta #1

Sí, es posible; de lo contrario, funciones sincrónicas como casper.exists no tendrían sentido.

En tu ejemplo, no_error nunca podría ser true, porque la devolución de llamada casper.start se ejecuta de manera asíncrona en un momento en que if (no_error) ya ha sido evaluada.

Tienes que anidar algunos pasos (todas las funciones wait* y then* son pasos) para hacer esto:

var casper = require('casper').create();
var no_error = false;

casper.start('http://casperjs.org/', function() {
    this.echo(this.getTitle());
    no_error = true;
});

casper.then(function(){
    if (no_error) {
        casper.thenOpen('http://phantomjs.org', function() {
            this.echo(this.getTitle());
        });
    }
});

casper.run();

Puedes anidar funciones de pasos, pero debes tener en cuenta que no debes usar una función sincrónica después de un paso, porque se ejecutará al revés.

casper.then(function(){
    casper.thenOpen('http://phantomjs.org', function() {
        this.echo("1: " + this.getTitle());
    });
    this.echo("2: " + this.getTitle());
});

imprimirá primero 2 y luego 1.

síncrona

Si los datos de la condición se devuelven de manera sincrónica, entonces puedes evaluarlos directamente

casper.start('http://casperjs.org/', function() {
    var array = this.evaluate(function(){....});
    if (array && array.length > 2) {
        this.thenOpen(...);
    }
});

Simplemente no hay necesidad de un paso adicional.

Asíncrono

Aquí es donde se pone interesante. Si, por ejemplo, tienes que ejecutar un script de larga duración en el contexto de la página (no se limita al contexto de la página), tendrás que esperar a su finalización en el contexto de Casper. Necesitarás una variable indicadora.

casper.thenEvaluate(function(){
    longRunningFunction(function callback(){
        window.__someIndicator = true;
    });
});

casper.waitFor(function check(){
    return this.evaluate(function(){
        return !!window.__someIndicator;
    });
}, function then(){
    this.thenOpen(...);
}, function onTimeout(){
    this.echo("failed");
    this.thenOpen(...); // open something else
});

A veces no tienes un callback posible. En este caso, probablemente el DOM cambiará y tendrás que esperar a esos cambios.

Conclusión

El ejemplo en el primer fragmento no es realmente útil y debería ser reemplazado por uno de los otros enfoques.