jQuery 如何在phantomjs中等待元素可见性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16807212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to wait for element visibility in phantomjs
提问by yegor256
Users click this link:
用户点击此链接:
<span onclick="slow_function_that_fills_the_panel(); $('#panel').show();">
Now I'm simulating the click in phantomjs:
现在我正在模拟 phantomjs 中的点击:
page.evaluate(
function() { $("#panel").click(); }
);
console.log('SUCCESS');
phantom.exit();
Phantom exits before the slow function ends its execution and the DIV becomes visible. How can I implement waiting?
Phantom 在慢函数结束执行并且 DIV 变得可见之前退出。如何实现等待?
回答by Chad Scira
Heres a spin of Cybermaxs's answer:
这是 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);
}
Example of use:
使用示例:
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
});
It's a little easier when you use a config variable.
使用配置变量时会更容易一些。
回答by Steven de Salas
PhantomJS runs asynchronously by default, causing problems like the one you describe above (where the script finishes before your results are ready)
PhantomJS 默认是异步运行的,会导致你上面描述的问题(脚本在你的结果准备好之前完成)
However there is nothing to stop you using it in a synchronous way.
但是,没有什么可以阻止您以同步方式使用它。
Just use phantom.page.sendEvent('mousemove')
in a while loop. This will keep looping through the event pump until the webkit engine loads your page or processes any necessary browser events.
只需phantom.page.sendEvent('mousemove')
在 while 循环中使用。这将一直循环通过事件泵,直到 webkit 引擎加载您的页面或处理任何必要的浏览器事件。
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');
Note that page.loading
can also be any other boolean condition, for example:
请注意,page.loading
也可以是任何其他布尔条件,例如:
do { phantom.page.sendEvent('mousemove'); }
while (page.evaluate(function() {return $("#panel").is(":visible");}));
I discovered this approach while working on the triflejs.orgproject (the Internet Explorer version of phantom) trying to emulate calls to trifle.wait(ms)
inside the PhantomJS environment.
我在从事triflejs.org项目(Phantom的 Internet Explorer 版本)时发现了这种方法,试图模拟trifle.wait(ms)
对 PhantomJS 环境内部的调用。
回答by Cybermaxs
My approach for this scenario is to wait until "something" is done or true. I highly suggest you to test waitfor.js.
对于这种情况,我的方法是等到“某事”完成或为真。我强烈建议你测试waitfor.js。
demo.html
演示.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
演示脚本.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);
}
});
}
This script evaluate $('#thediv').is(':visible')
(classic Jquery code) every 500 ms to check if the div is visible.
此脚本$('#thediv').is(':visible')
每 500 毫秒评估一次(经典的 Jquery 代码)以检查 div 是否可见。
回答by Chris Fortune
Inside page.evaluate(), use the self.loadingproperty to test for doneness ....
在 page.evaluate() 中,使用self.loading属性来测试完成度....
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();
});