水豚,骚灵,PhantomJS,evaluate_script,回调
问题描述:
我使用下面的代码,它使用了imagesLoaded包回调告诉我,当与特定csspath元素已加载完所有图片:水豚,骚灵,PhantomJS,evaluate_script,回调
imagesLoadedScript = "imagesLoaded('#{csspath}', { background: true }, function(message) { console.log('PHANTOM CLIENT REPORTING: #{csspath} Images Loaded'); return message; })"
imagesLoadedScript = imagesLoadedScript.strip.gsub(/\s+/,' ')
@session.evaluate_script(imagesLoadedScript)
console.log语句在调试时检查PhantomJS日志时表明,在进入下一个语句之前,Capybara/Poltergiest并未等待图像加载,如预期那样。我也不能根据需要从回调内部返回真实(或错误)的值。
水豚用
{"command_id":"678f1e2e-4820-4631-8cd6-413ce6f4b66f","response":"(cyclic structure)"}
任何回应有关于如何从回调内部,通过evaluate_script执行的函数返回一个值的任何想法?
非常感谢。
答
TLDR;你不能
evaluate_script
不支持异步功能 - 你必须返回你以某种方式传递的功能,想要做你想做的是执行imagesLoaded
脚本,并有回调设置一个全球性的结果。变量,然后在一个evaluate_script获取全球的结果循环,直到它是你想要的东西 - 一个非常基本的实现会是这样的
imagesLoadedScript = "window.allImagesLoaded = false; imagesLoaded('#{csspath}', { background: true }, function() { window.my_images_loaded = true })"
@session.execute_script(imagesLoadedScript)
while [email protected]_script('window.allImagesLoaded')
sleep 0.05
end
显然,这可以由一个超时的能力更灵活等
第二个选择是编写一个自定义capy巴拉选择器类型的图像与loaded
过滤器,但需要进行背景图像检查,它会变得非常复杂,可能太慢而无用。
答
以防万一以后有人发现。
我大致做了Thomas Walpole在他的回答中以更迂回的方式提出的建议,但利用了Poltergeist固有的等待能力;
#to check that the target has loaded its images, run images loaded
#after a small timeout to allow the page to get the images
#append a marker div to the dom if the images have successfully loaded
imagesLoadedScript = "var item = document.querySelector('#{csspath}');
window.scroll(0, item.offsetTop);
function imagesDone(path, fn) {
imagesLoaded(path, function(instance) {
console.log('PHANTOM CLIENT REPORTING: ' + path + ' Images Loaded');
fn(true);
})
}
setTimeout(function(){
imagesDone('#{csspath}', function(done) {
var markerDiv = document.createElement('div');
markerDiv.id = 'ImagesLoadedMarker';
document.getElementsByTagName('html')[0].appendChild(markerDiv);
});
}, 1000)"
#then we strip the new lines and spaces that we added to make it readable
imagesLoadedScript = imagesLoadedScript.strip.gsub(/\s+/,' ')
#now we just execute the script as we do not need a return value
@session.execute_script(imagesLoadedScript)
#then we check for the marker, using capybara's inbuilt waiting time
if @session.has_xpath? "//*[@id ='ImagesLoadedMarker']"
Rails.logger.debug "!!!!! PhantomClient: Images Loaded Reporting: #{csspath} Images Loaded: Check Time #{Time.now} !!!!!"
@session.save_screenshot(file_path, :selector => csspath)
else
Rails.logger.debug "!!!!! PhantomClient: Images Loaded Reporting: #{csspath} Images NOT Loaded: Check Time #{Time.now} !!!!!"
@session.save_screenshot(file_path, :selector => csspath)
end
谢谢托马斯我张贴我的解决方案上面。花了我一段时间才意识到我正在尝试做一些不可能的事情。 – Tom
@Tom这也会起作用 - 你也可以做一些事情,比如向html/body元素中添加一个类,而不是在页面中插入新元素(如果你用'n - 儿童选择器等)。 –
@Tom - 仅供参考,Capybara可能会在其下一个版本中支持这个用例 - https://github.com/teamcapybara/capybara/pull/1927 - 不知道Poltergeist能支持它多久 –