2013-05-29 20 views
24

Kullanıcılar bu bağlantıyı tıklayın nasıl: yavaş işlevi yürütme biter ve öncephantomjs öğesi görüş için beklemek

page.evaluate(
    function() { $("#panel").click(); } 
); 
console.log('SUCCESS'); 
phantom.exit(); 

Phantom çıkar:

<span onclick="slow_function_that_fills_the_panel(); $('#panel').show();"> 

Şimdi phantomjs içinde tıklatır gibi değilim DIV görünür hale gelir. Beklemeyi nasıl uygulayabilirim?

+0

aptal çözüm setTimeout() – igor

cevap

7

Bu senaryodaki yaklaşımım, "bir şey" tamamlanana veya doğru olana kadar beklemektir. waitfor.js'u test etmenizi öneririm.

demo.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <script src="http://code.jquery.com/jquery-1.9.1.js"></script> 
    <title>Test</title> 
</head> 
<body id="body"> 

    <div id="thediv">Hello World !</div> 

    <script type="text/javascript"> 
     $('#thediv').hide(); 
     setTimeout(function() { 
      $('#thediv').show(); 
     }, 3000); 

    </script> 
</body> 
</html> 

demoscript.js

var page = require('webpage').create(); 
var system = require('system'); 

function waitFor(testFx, onReady, timeOutMillis) { 
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 5000, //< Default Max Timout is 5s 
     start = new Date().getTime(), 
     condition = false, 
     interval = setInterval(function() { 
      if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { 
       // If not time-out yet and condition not yet fulfilled 
       condition = (typeof (testFx) === "string" ? eval(testFx) : testFx()); //< defensive code 
      } else { 
       if (!condition) { 
        // If condition still not fulfilled (timeout but condition is 'false') 
        //console.log("'waitFor()' timeout"); 
        typeof (onReady) === "string" ? eval(onReady) : onReady(); 
        clearInterval(interval); 
        //phantom.exit(1); 
       } else { 
        // Condition fulfilled (timeout and/or condition is 'true') 
        console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); 
        typeof (onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled 
        clearInterval(interval); //< Stop this interval 
       } 
      } 
     }, 500); //< repeat check every 500ms 
}; 

if (system.args.length != 1) { 
    console.log('invalid call'); 
    phantom.exit(1); 
} else { 
    //adapt the url to your context 
    page.open('http://localhost:40772/demo.html', function (status) { 
     if (status !== 'success') { 
      console.log('Unable to load the address!'); 
      phantom.exit(); 
     } else { 
      waitFor(
       function() { 
        return page.evaluate(function() { 
         return $('#thediv').is(':visible'); 
        }); 
       }, 
       function() { 
        page.render('page.png'); 
        phantom.exit(); 
       }, 5000); 
     } 
    }); 
} 

Bu komut dosyası div görünür olup olmadığını kontrol etmek $('#thediv').is(':visible') (klasik jQuery kodu) her 500 ms değerlendirir.

+0

Müthiş bir çözümdür .... Doneness test etmek self.loading özelliğini kullanın. 'Promise' pattern @see https://github.com/amir20/phantomjs-node/issues/431 – loretoparisi

22

İşte Cybermaxs cevabı bir spin Kullanım

function waitFor ($config) { 
    $config._start = $config._start || new Date(); 

    if ($config.timeout && new Date - $config._start > $config.timeout) { 
     if ($config.error) $config.error(); 
     if ($config.debug) console.log('timedout ' + (new Date - $config._start) + 'ms'); 
     return; 
    } 

    if ($config.check()) { 
     if ($config.debug) console.log('success ' + (new Date - $config._start) + 'ms'); 
     return $config.success(); 
    } 

    setTimeout(waitFor, $config.interval || 0, $config); 
} 

Örnek:

waitFor({ 
    debug: true, // optional 
    interval: 0, // optional 
    timeout: 1000, // optional 
    check: function() { 
     return page.evaluate(function() { 
      return $('#thediv').is(':visible'); 
     }); 
    }, 
    success: function() { 
     // we have what we want 
    }, 
    error: function() {} // optional 
}); 

bir yapılandırma değişkeni kullandığınızda Biraz daha kolaydır.

+0

THANKYOU nedeniyle, bu düğümü 'phantom' için nasıl uygulayacağımı bilmiyorum! İki gün boyunca, bir formun gönderilip gönderilmediğini (körü körüne umut veren bir setTimeout değil) görüp görmediğimi kontrol etmek için yarım düzine kadar başka bir yol denedim ve bu benim için kusursuz çalışan tek kişi. +1 – indextwo

14

PhantomJS (sonuçlarınız hazır önce komut sona) Yukarıdaki açıkladığınız

Ancak eşzamanlı bir şekilde kullanmış sizi durdurmak için hiçbir şey yokmuş gibi sorunlara yol varsayılan olarak uyumsuz olarak çalışır.

Bir süre döngüsünde yalnızca phantom.page.sendEvent('mousemove') kullanın. Bu, webkit motoru sayfanızı yükleyene veya gerekli herhangi bir tarayıcı olayını işleyene kadar etkinlik pompasında dolaşmaya devam edecektir. Aramaları özeniyor triflejs.org projenin (hayali Internet Explorer sürüm) üzerinde çalışırken

do { phantom.page.sendEvent('mousemove'); } 
while (page.evaluate(function() {return $("#panel").is(":visible");})); 

Ben bu yaklaşımı keşfetti: page.loading da örneğin başka boole durum olabileceğini

var page = require('webpage').create(); 

// Step 1: View item 
page.open('http://localhost/item3324.php'); 
do { phantom.page.sendEvent('mousemove'); } while (page.loading); 
page.render('step1-viewitem.png'); 

// Step 2: Add to cart 
page.evaluate(function() {$('#add-to-cart').click(); }); 
do { phantom.page.sendEvent('mousemove'); } while (page.loading); 
page.render('step2-viewcart.png'); 

// Step 3: Confirm contents 
page.evaluate(function() {$('#confirm-cart').click(); }); 
do { phantom.page.sendEvent('mousemove'); } while (page.loading); 
page.render('step3-confirm.png'); 

Not PhantomJS ortamında trifle.wait(ms)'a.

+0

can phantom.page.sendEvent ('mousemove') 'mobil sayfada çalışıyor mu? –

+0

@FengYu emin bir şey. mousemove, kullanılacak doğru olaydır. Phantom (masaüstü tarayıcınız gibi) bir mobil sayfasını tanımıyor. Tek bildiği şey, bir web sayfasını açıp bunu ortaya çıkarmasıdır. –

+0

'page.sendEvent ('mousemove')' işlevini while döngüsünde kaldırabilir miyim? –

0

page.evaluate İçinde(),

var fs = require('fs'); 
path = '/path/to/file.html'; 
address = 'http://google.com';  

page.open(address, function (status) { 
    if (status !== 'success') { 
     console.log('Unable to access page'); 
    } else { 
     var p = page.evaluate(function() { 
      if(!self.loading){ // ah, such beauty 
       return document.documentElement.outerHTML; 
      } 
     }); 
    fs.write(path, p, 'w'); 
    } 
    phantom.exit(); 
});  
İlgili konular