97 votes

Ce que fait ' puis ' vraiment dire dans CasperJS

Je suis l'aide de CasperJS pour automatiser une série de clics, les formulaires, l'analyse de données, etc par le biais d'un site web.

Casper semble être regroupées dans une liste de présélection des étapes dans la forme d' then des déclarations (voir l'exemple ici: http://casperjs.org/quickstart.html) mais il est difficile de savoir ce qui déclenche l'instruction suivante pour exécuter.

Par exemple, est - then d'attente pour toutes les demandes en attente pour la terminer? N' injectJS comptent comme une demande en attente? Qu'advient-il si j'ai un then déclaration imbriquée enchaîné à la fin de l' open déclaration?

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
});

Je suis à la recherche d'une explication technique de la façon dont les flux de travaux de CasperJS. Mon problème est que mon dernier then déclaration (ci-dessus) s'exécute avant que mes casper.open et je ne sais pas pourquoi.

93voto

NiKo Points 5023

then() essentiellement ajoute une nouvelle étape de navigation dans une pile. Une étape est une fonction javascript qui peut faire de deux choses différentes:

  1. d'attente pour l'étape précédente, le cas échéant, être exécuté
  2. d'attente pour une demande d'url et la page liée à la charge

Prenons un simple scénario de navigation:

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

casper.start();

casper.then(function step1() {
    this.echo('this is step one');
});

casper.then(function step2() {
    this.echo('this is step two');
});

casper.thenOpen('http://google.com/', function step3() {
    this.echo('this is step 3 (google.com is loaded)');
});

Vous pouvez imprimer toutes les créé des étapes à l'intérieur de la pile comme ceci:

require('utils').dump(casper.steps.map(function(step) {
    return step.toString();
}));

Ce qui donne:

$ casperjs test-steps.js
[
    "function step1() { this.echo('this is step one'); }",
    "function step2() { this.echo('this is step two'); }",
    "function _step() { this.open(location, settings); }",
    "function step3() { this.echo('this is step 3 (google.com is loaded)'); }"
]

Avis de l' _step() fonction qui a été ajoutée automatiquement par CasperJS pour charger l'url pour nous; lorsque l'url est chargé, l'étape suivante disponible dans la pile - qui est - step3() - est appelée.

Lorsque vous avez défini vos étapes de navigation, run() exécute un par un de manière séquentielle:

casper.run();

Note: la fonction de rappel/auditeur des choses est une mise en œuvre de la Promesse de modèle.

33voto

starlocke Points 715

then() enregistre uniquement une série d'étapes.

run() et sa famille de coureur des fonctions, des rappels, et les auditeurs, sont tout ce que font réellement le travail de l'exécution de chaque étape.

Chaque fois qu'une étape est terminée, CasperJS vérifiera les 3 indicateurs: pendingWait, loadInProgress, et navigationRequested. Si l'un de ces drapeaux est vrai, alors ne rien faire, aller ralenti jusqu'à une date ultérieure (setInterval style). Si aucune de ces options est vrai, alors la prochaine étape sera exécuté.

Comme de CasperJS 1.0.0-RC4, il existe un défaut, où, dans certaines temps en fonction des circonstances, la "essayer de faire la prochaine étape de la méthode sera déclenchée avant de CasperJS eu le temps de lever l'une de l' loadInProgress ou navigationRequested drapeaux. La solution est de faire de l'un de ces drapeaux avant de quitter une étape où les drapeaux devraient être augmentés (ex: hisser un drapeau soit avant ou après avoir posé pour un casper.click()), peut-être comme ceci:

(Note: Ce n'est qu'une illustration de plus comme psuedocode que bon CasperJS forme...)

step_one = function(){
    casper.click(/* something */);
    do_whatever_you_want()
    casper.click(/* something else */); // Click something else, why not?
    more_magic_that_you_like()
    here_be_dragons()
    // Raise a flag before exiting this "step"
    profit()
}

Pour conclure cette solution en une seule ligne de code, j'ai introduit blockStep() dans cette github pull request, s'étendant click() et clickLabel() comme un moyen pour aider à garantir que nous obtenons le comportement à adopter lors de l'utilisation d' then(). Consulter la demande pour plus d'info, des modèles d'utilisation, et un minimum de fichiers de test.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X