web-gelistirme-sc.com

'O zaman' CasperJS'de Gerçekten Ne İfade Ediyor?

CasperJS'i bir dizi tıklamayı, tamamlanmış formu, veriyi vb. Bir web sitesi aracılığıyla otomatikleştirmek için kullanıyorum.

Casper, then deyimleri şeklinde önceden ayarlanmış adımlar listesi halinde organize edilmiş gibi görünüyor (burada örneklerine bakın: http://casperjs.org/quickstart.html ) ancak bir sonraki ifadenin gerçekte çalıştırılmasını tetikleyen şey belirsiz .

Örneğin, then bekleyen tüm isteklerin tamamlanmasını bekliyor mu? injectJS bekleyen bir istek olarak sayılıyor mu? Yuvalanmış bir then deyiminin sonuna kadar zincirlenmiş bir open deyimi varsa ne olur?

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'de akışın nasıl çalıştığına dair teknik bir açıklama arıyorum. Özel sorunum, son then ifademin (yukarıdaki) benim casper.open ifademden önce çalışması ve nedenini bilmiyorum.

97
bendytree

then() temel olarak bir yığında yeni bir gezinme adımı ekler. Bir adım, iki farklı şey yapabilen bir javascript işlevidir:

  1. önceki adımı bekliyor - varsa - yürütülüyor
  2. istenen bir URL ve ilgili sayfanın yüklenmesini bekliyor

Basit bir gezinme senaryosu alalım:

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

Yığındaki tüm oluşturulan adımları şöyle yazdırabilirsiniz:

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

Bu verir:

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

URL'yi bize yüklemek için CasperJS tarafından otomatik olarak eklenen _step() işlevine dikkat edin; URL yüklendiğinde, yığında mevcut olan bir sonraki adıma - ki bu step3() - denir.

Gezinme adımlarınızı tanımladığınızda, run() bunları sırayla sırayla yürütür:

casper.run();

Dipnot: geri çağrı/dinleyici olayı, Söz modelinin bir uygulamasıdır.

93
NiKo

then() sadece bir dizi adımı kaydeder.

run() ve koşucu işlevleri ailesi, geri aramalar ve dinleyiciler, her adımı yerine getirme işini gerçekten yapan şeydir.

Bir adım tamamlandığında, CasperJS, 3 bayrakla kontrol eder: pendingWait, loadInProgress ve navigationRequested. Bu bayraklardan herhangi biri doğruysa, o zaman hiçbir şey yapmayın, daha sonraki bir zamana kadar boşa gidin (setInterval style). Bu bayraklardan hiçbiri doğru değilse, bir sonraki adım uygulanacaktır.

CasperJS 1.0.0-RC4'ten itibaren, belirli bir zamana dayalı koşullar altında, CasperJS'in loadInProgress veya navigationRequested bayraklarından birini yükseltme zamanı gelmeden önce, "sonraki adımı yapmaya çalış" yönteminin tetikleneceği bir kusur vardır. Çözüm, bu bayrakların yükseltilmesi beklenen basamaklardan herhangi birini terk etmeden önce bu bayraklardan birini yükseltmektir (örneğin: casper.click() isteğinde bulunmadan önce veya sonra bir bayrak kaldırın), belki:

(Not: Bu sadece örnek niteliğindedir, uygun CasperJS formundan çok psuedocode gibidir ...)

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

Bu çözümü tek bir kod satırına sığdırmak için blockStep() bu github pull isteği 'de, click() ve clickLabel() öğelerini genişlettiğimizi, then() kullanırken beklenen davranışı edin. Daha fazla bilgi, kullanım şekli ve minimum test dosyaları için istekleri kontrol edin.

33
starlocke

CasperJS Belgelerine Göre :

then()

İmza:then(Function then)

Bu yöntem, basit bir işlev sağlayarak yığına yeni bir gezinme adımı eklemenin standart yoludur:

casper.start('http://google.fr/');

casper.then(function() {
  this.echo('I\'m in your google.');
});

casper.then(function() {
  this.echo('Now, let me write something');
});

casper.then(function() {
  this.echo('Oh well.');
});

casper.run();

İstediğiniz kadar adım ekleyebilirsiniz. Geçerli Casper örneğinin, adım işlevleri içindeki sizin için this anahtar sözcüğünü otomatik olarak bağladığını unutmayın.

Tanımladığınız tüm adımları çalıştırmak için, run() method ve voila 'yı arayın.

Not:start() yöntemini kullanmak için then() / casper örneğini kullanmalısınız.

Uyarı: _ ​​then() öğesine eklenen adım işlevleri iki farklı durumda işlenir:

  1. önceki adım işlevi yürütüldüğünde,
  2. önceki ana HTTP isteği yerine getirildiğinde ve sayfa yüklü;

Sayfa yüklendi; DOMReady olayı tetiklendiğinde mi? "Tüm isteklerin bitmesi" mi? "Tüm uygulama mantığı gerçekleştiriliyor" mu? Veya "tüm elemanlar oluşturuluyor"? Cevap her zaman içeriğe bağlıdır. Bu nedenle, gerçekte beklediğiniz şeyleri açıkça kontrol altında tutmak için her zaman waitFor() family yöntemlerini kullanmaya teşvik edilirsiniz.

Yaygın bir hile kullanmak waitForSelector() : işlevini kullanmaktır.

casper.start('http://my.website.com/');

casper.waitForSelector('#plop', function() {
  this.echo('I\'m sure #plop is available in the DOM');
});

casper.run();

Sahne arkasında, Casper.prototype.then için kaynak kodu aşağıda gösterilmiştir:

/**
 * Schedules the next step in the navigation process.
 *
 * @param  function  step  A function to be called as a step
 * @return Casper
 */
Casper.prototype.then = function then(step) {
    "use strict";
    this.checkStarted();
    if (!utils.isFunction(step)) {
        throw new CasperError("You can only define a step as a function");
    }
    // check if casper is running
    if (this.checker === null) {
        // append step to the end of the queue
        step.level = 0;
        this.steps.Push(step);
    } else {
        // insert substep a level deeper
        try {
            step.level = this.steps[this.step - 1].level + 1;
        } catch (e) {
            step.level = 0;
        }
        var insertIndex = this.step;
        while (this.steps[insertIndex] && step.level === this.steps[insertIndex].level) {
            insertIndex++;
        }
        this.steps.splice(insertIndex, 0, step);
    }
    this.emit('step.added', step);
    return this;
};

Açıklama:

Başka bir deyişle, then(), gezinme işleminde bir sonraki adımı programlar.

then() çağrıldığında, adım olarak adlandırılacak bir parametre olarak bir işlevden geçirilir.

Bir örneğin başlatılıp başlatılmadığını kontrol eder ve başlatılmadıysa, aşağıdaki hatayı görüntüler:

CasperError: Casper is not started, can't execute `then()`.

Daha sonra, page nesnesinin null olup olmadığını kontrol eder.

Koşul doğruysa, Casper yeni bir page nesnesi oluşturur.

Bundan sonra, then(), bir işlev olup olmadığını kontrol etmek için step parametresini doğrular.

Parametre bir işlev değilse, aşağıdaki hatayı görüntüler:

CasperError: You can only define a step as a function

Ardından, işlev Casper'ın çalışıp çalışmadığını kontrol eder.

Casper çalışmıyorsa, then(), adı sıranın sonuna ekler.

Aksi takdirde, eğer Casper çalışıyorsa, bir önceki adıma göre daha derine bir alt basamağa ekler.

Son olarak, then() işlevi bir step.added olayı göndererek sonlandırır ve Casper nesnesini döndürür.

0
Grant Miller