2017-10-20 174 views
0

我使用下面的代碼,它使用了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執行的函數返回一個值的任何想法?

非常感謝。

回答

1

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能支持它多久 –

0

以防萬一以後有人發現。

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