如何在phantomjs中等待元素可见性
how to wait for element visibility in phantomjs
用户点击此链接:
<span onclick="slow_function_that_fills_the_panel(); $('#panel').show();">
现在我正在模拟phantomjs中的点击:
page.evaluate(
function() { $("#panel").click(); }
);
console.log('SUCCESS');
phantom.exit();
在慢函数结束执行并且DIV变得可见之前,Phantom退出。我如何实现等待?
cybermax的回答如下:
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);
}
使用示例:
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
});
默认情况下,PhantomJS是异步运行的,这会导致上面描述的问题(脚本在结果准备好之前就结束了)
但是没有什么可以阻止您以同步方式使用它。
在while循环中使用phantom.page.sendEvent('mousemove')
。这将通过事件泵循环,直到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');
注意page.loading
也可以是任何其他布尔条件,例如:
do { phantom.page.sendEvent('mousemove'); }
while (page.evaluate(function() {return $("#panel").is(":visible");}));
我在trilejs.org项目(Internet Explorer版本的phantom)上工作时发现了这种方法,试图在PhantomJS环境中模拟对trifle.wait(ms)
的调用。
对于这种情况,我的方法是等待,直到"某事"完成或为真。我强烈建议你测试一下waitfor.js.
替换
<!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);
}
});
}
此脚本每500毫秒评估$('#thediv').is(':visible')
(经典Jquery代码)以检查div是否可见。
在page.evaluate()中,使用self。加载属性来测试是否完成....
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();
});
相关文章:
- Chrome扩展:等待元素加载(async js)
- jQuery-等待此元素,然后执行1次
- 如何正确地等待元素获得正确的宽度,然后在Angular 2中访问它
- Selenium-webdriver (Java Script) 等待元素消失
- Selenium webdriver JS-如何等待元素可见
- 在promise链中等待DOM元素中的突变
- jQuery文档是否准备好等待通过Backbone动态注入的html元素
- 在 Capybara 中,如何让 #find 等待具有相同类的不同元素出现
- 无法在 jquery 中获取元素动画以等待另一个元素动画
- 实现等待元素存在 N 秒,然后使用 JavaScript 和 jQuery lib 与元素交互
- 等待元素更改其值(文本)
- 如何在WebDriverJS中等待元素可点击
- 如何在phantomjs中等待元素可见性
- 指令如何等待元素'动态插值属性被处理?
- 等待元素显示给用户
- MutationObserver错误:我怎么能等待元素的创建呢?
- Selenium:如何等待元素的文本发生变化
- onsenui 2等待元素被加载
- 我如何使用量角器和我的文件配置等待元素出现?
- 等待元素出现Javascript不触发Raise事件