javascript - run - phantomjs svg
Cómo esperar la visibilidad del elemento en phantomjs. (4)
Aquí hay un giro de la respuesta de Cybermaxs:
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);
}
Ejemplo de uso:
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
});
Es un poco más fácil cuando usas una variable de configuración.
Los usuarios hacen clic en este enlace:
<span onclick="slow_function_that_fills_the_panel(); $(''#panel'').show();">
Ahora estoy simulando el click en phantomjs:
page.evaluate(
function() { $("#panel").click(); }
);
console.log(''SUCCESS'');
phantom.exit();
Phantom sale antes de que la función lenta termine su ejecución y el DIV se haga visible. ¿Cómo puedo implementar la espera?
Dentro de page.evaluate (), use la propiedad self.loading para probar la cocción ...
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();
});
Mi enfoque para este escenario es esperar hasta que "algo" se haga o sea verdadero. Te sugiero que waitfor.js .
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);
}
});
}
Este script evalúa $(''#thediv'').is('':visible'')
(código Jquery clásico) cada 500 ms para comprobar si el div es visible.
PhantomJS se ejecuta de forma asíncrona de manera predeterminada, causando problemas como el que describió anteriormente (donde el script termina antes de que sus resultados estén listos)
Sin embargo, no hay nada que le impida utilizarlo de forma sincrónica.
Simplemente use phantom.page.sendEvent(''mousemove'')
en un bucle while. Esto seguirá circulando a través de la bomba de eventos hasta que el motor de webkit cargue su página o procese los eventos necesarios del navegador.
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'');
Tenga en cuenta que page.loading
también puede ser cualquier otra condición booleana, por ejemplo:
do { phantom.page.sendEvent(''mousemove''); }
while (page.evaluate(function() {return $("#panel").is(":visible");}));
Descubrí este enfoque mientras trabajaba en el proyecto triflejs.org (la versión de Internet Explorer de phantom) que intentaba emular llamadas a trifle.wait(ms)
dentro del entorno PhantomJS.