Estoy usando CasperJS para automatizar una serie de clics, formularios completados, análisis de datos, etc. a través de un sitio web.
Casper parece estar organizado en una lista de pasos preestablecidos en forma de then
declaraciones (vea su ejemplo aquí: http://casperjs.org/quickstart.html ) pero no está claro qué desencadena la siguiente declaración para que se ejecute realmente.
Por ejemplo, ¿ then
espera a que se completen todas las solicitudes pendientes? ¿ injectJS
Cuenta como una solicitud pendiente? ¿Qué sucede si tengo una then
declaración anidada, encadenada al final de una open
declaración?
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
});
Estoy buscando una explicación técnica de cómo funciona el flujo en CasperJS. Mi problema específico es que mi última then
declaración (arriba) se ejecuta antes de mi casper.open
declaración y no sé por qué.
fuente
flow
de casperjs, pero descubrí que básicamente no se puede hacer referencia a casper desde dentro de unaevaluate
llamada. (es decir, no puede abrir una nueva URL, registro, eco, etc.). Entonces, en mi caso, se llamaba a evaluar, pero no había forma de interactuar con el mundo exterior.evaluate()
es para código que se ejecuta en el "navegador", en el DOM de la página que está navegando phantomjs. Entonces no haycasper.open
allí, pero podría haber jQuery. Entonces tu ejemplo no tiene sentido, pero todavía me pregunto qué es lo quethen()
realmente hace.Respuestas:
then()
básicamente agrega un nuevo paso de navegación en una pila. Un paso es una función de JavaScript que puede hacer dos cosas diferentes:Tomemos un escenario de navegación simple:
Puede imprimir todos los pasos creados dentro de la pila de esta manera:
Eso da:
Observe la
_step()
función que CasperJS ha agregado automáticamente para cargar la URL por nosotros; cuando se carga la URL, se llama al siguiente paso disponible en la pila, que esstep3()
.Cuando haya definido sus pasos de navegación,
run()
ejecútelos uno por uno secuencialmente:Nota al pie: la devolución de llamada / escucha es una implementación del patrón Promise .
fuente
then()
simplemente registra una serie de pasos.run()
y su familia de funciones de corredor, devoluciones de llamada y oyentes, son todos los que realmente hacen el trabajo de ejecutar cada paso.Cada vez que se completa un paso, CasperJS comprobarán contra 3 banderas:
pendingWait
,loadInProgress
, ynavigationRequested
. Si alguna de esas banderas es verdadera, entonces no haga nada, permanezca inactivo hasta un momento posterior (setInterval
estilo). Si ninguno de esos indicadores es verdadero, se ejecutará el siguiente paso.A partir de CasperJS 1.0.0-RC4, existe una falla, donde, bajo ciertas circunstancias basadas en el tiempo, el método "intentar hacer el siguiente paso" se activará antes de que CasperJS tenga tiempo de activar una de las banderas
loadInProgress
onavigationRequested
. La solución es levantar una de esas banderas antes de salir de cualquier paso donde se espera que se levanten esas banderas (por ejemplo, levantar una bandera antes o después de pedir unacasper.click()
), tal vez así:(Nota: Esto es solo ilustrativo, más como un psuedocode que un formulario CasperJS adecuado ...)
Para resumir esa solución en una sola línea de código,
blockStep()
presenté en esta solicitud de extracción de github , extendiendoclick()
yclickLabel()
como un medio para ayudar a garantizar que obtenemos el comportamiento esperado al usarthen()
. Consulte la solicitud para obtener más información, patrones de uso y archivos de prueba mínimos.fuente
blockStep
, en mi humilde opiniónSegún la documentación de CasperJS :
then()
Firma:
then(Function then)
Detrás de escena, el código fuente de
Casper.prototype.then
se muestra a continuación:Explicación:
En otras palabras,
then()
programa el siguiente paso del proceso de navegación.Cuando
then()
se llama, se le pasa una función como parámetro que debe llamarse como paso.Comprueba si se ha iniciado una instancia y, si no, muestra el siguiente error:
A continuación, comprueba si el
page
objeto esnull
.Si la condición es verdadera, Casper crea un nuevo
page
objeto.Después de eso,
then()
valida elstep
parámetro para verificar si no es una función.Si el parámetro no es una función, muestra el siguiente error:
Luego, la función verifica si Casper se está ejecutando.
Si Casper no se está ejecutando,
then()
agrega el paso al final de la cola.De lo contrario, si Casper se está ejecutando, inserta un subpaso un nivel más profundo que el paso anterior.
Finalmente, la
then()
función concluye emitiendo unstep.added
evento y devuelve el objeto Casper.fuente