如何在phantomjs中等待元素可见性

用户点击此链接:

 

现在我正在模拟phantomjs中的点击:

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

Phantom在慢速函数结束执行之前退出,DIV变为可见。 我该如何实施等待?

这是Cyber​​maxs的回答:

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

我在尝试模拟PhantomJS环境中对trifle.wait(ms)调用时,在triflejs.org项目(Internet Explorer版本的幻像)上发现了这种方法。

我对这种情况的处理方法是等到“某事”完成或为真。 我强烈建议你测试waitfor.js 。

demo.html

     Test   
Hello World !

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