水豚,骚灵,PhantomJS,evaluate_script,回调

水豚,骚灵,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过滤器,但需要进行背景图像检查,它会变得非常复杂,可能太慢而无用。

+0

谢谢托马斯我张贴我的解决方案上面。花了我一段时间才意识到我正在尝试做一些不可能的事情。 – Tom

+0

@Tom这也会起作用 - 你也可以做一些事情,比如向html/body元素中添加一个类,而不是在页面中插入新元素(如果你用'n - 儿童选择器等)。 –

+0

@Tom - 仅供参考,Capybara可能会在其下一个版本中支持这个用例 - https://github.com/teamcapybara/capybara/pull/1927 - 不知道Poltergeist能支持它多久 –

以防万一以后有人发现。

我大致做了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