97

CasperJS を使用して、一連のクリック、フォームへの入力、データの解析などを Web サイトで自動化しています。

thenCasper は、ステートメントの形式で事前設定されたステップのリストに編成されているようです(ここで例を参照してください: 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ステートメントの前に実行され、理由がわからないことです。

4

3 に答える 3

93

then()基本的に、スタックに新しいナビゲーション ステップを追加します。ステップは、次の 2 つの異なることを実行できる JavaScript 関数です。

  1. 前のステップがあれば - 実行されるのを待っている
  2. リクエストされた URL と関連ページが読み込まれるのを待っています

簡単なナビゲーション シナリオを見てみましょう。

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

次のように、スタック内で作成されたすべてのステップを印刷できます。

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

それは与える:

$ 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)'); }"
]

_step()URL をロードするために CasperJS によって自動的に追加された関数に注目してください。URL が読み込まれると、スタックで使用可能な次のステップ (つまり、)step3()が呼び出されます。

ナビゲーション ステップを定義したら、run()それらを 1 つずつ順番に実行します。

casper.run();

脚注:コールバック/リスナーはPromise パターンの実装です。

于 2012-08-14T17:51:25.980 に答える
33

then()一連のステップを登録するだけです。

run()ランナー関数、コールバック、リスナーのファミリーはすべて、各ステップを実行する作業を実際に行うものです。

pendingWaitステップが完了するたびに、CasperJSは3つのフラグ( 、、、loadInProgressおよび)をチェックしnavigationRequestedます。これらのフラグのいずれかが真の場合は、何もせず、後で(setIntervalスタイル)までアイドル状態にします。これらのフラグのいずれも真でない場合、次のステップが実行されます。

CasperJS 1.0.0-RC4の時点では、特定の時間ベースの状況下で、CasperJSがloadInProgressまたはnavigationRequestedフラグのいずれかを発生させる前に「次のステップを実行する」メソッドがトリガーされるという欠陥があります。解決策は、これらのフラグが立てられると予想されるステップを離れる前に、これらのフラグの1つを上げることです(例:を要求する前または後にフラグを立てるcasper.click())、おそらく次のようになります。

(注:これは単なる例示であり、適切なCasperJSフォームよりも擬似コードに似ています...)

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

そのソリューションを1行のコードにまとめるためにblockStep()、このgithubプルリクエストで、を拡張click()し、clickLabel()を使用したときに期待される動作が得られることを保証する手段として紹介しましたthen()。詳細、使用パターン、および最小テストファイルについては、リクエストを確認してください。

于 2012-11-01T21:43:30.510 に答える