Phantomjs 水豚,妖怪,幻影,求值脚本,回调
我正在使用以下代码,该代码使用带有回调的包来告诉我具有特定csspath的元素何时已完成其所有图像的加载:Phantomjs 水豚,妖怪,幻影,求值脚本,回调,phantomjs,capybara,poltergeist,Phantomjs,Capybara,Poltergeist,我正在使用以下代码,该代码使用带有回调的包来告诉我具有特定csspath的元素何时已完成其所有图像的加载: imagesLoadedScript = "imagesLoaded( '#{csspath}', { background: true }, function(message) { console.log('PHANTOM CLIENT REPORTING: #{csspath} Images Loaded'); return message; })" imagesL
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)
在debug打开的情况下检查PhantomJS日志时,console.log语句的计时表明,Capybara/Poltergiest在转到下一个语句之前并没有像预期的那样等待映像加载。我也不能像我所希望的那样从回调内部返回真值或假值
水豚的反应是
{"command_id":"678f1e2e-4820-4631-8cd6-413ce6f4b66f","response":"(cyclic structure)"}
有人知道如何在通过evaluate_脚本执行的函数中从回调函数内部返回值吗
非常感谢。TLDR;你不能
evaluate_脚本不支持异步函数-必须从传入的函数返回所需的结果。一种方法是执行imagesLoaded脚本,让回调函数设置一个全局变量,然后在一个evaluate_脚本上循环,获取全局变量的结果,直到它符合您的要求—一个非常基本的实现类似于
imagesLoadedScript = "window.allImagesLoaded = false; imagesLoaded( '#{csspath}', { background: true }, function() { window.my_images_loaded = true })"
@session.execute_script(imagesLoadedScript)
while !@session.evaluate_script('window.allImagesLoaded')
sleep 0.05
end
显然,这可以通过超时功能变得更加灵活,等等
第二个选项是为带有加载过滤器的图像编写自定义水豚选择器类型,尽管由于需要进行背景图像检查,这将变得非常复杂,而且可能太慢而无法使用。以防万一以后有人发现这一点 我大致按照托马斯·沃尔波尔(Thomas Walpole)在回答中的建议,以一种更迂回的方式,但利用了恶鬼固有的等待能力
#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,这也行得通-你也可以做一些事情,比如在html/body元素中添加一个类,而不是在页面中插入新元素,如果你使用第n个子选择器做任何事情,这可能会搞砸CSS,等等。@Tom-FYI,水豚可能会在下一个版本中支持这个用例——不过不确定在恶灵支持多久之后