2010-12-10 49 views
6

我使用Selenium來測試一個Web應用程序,我不允許修改應用程序的JavaScript代碼。我試圖通過使用GreaseMonkey來重寫XMLHttpRequest.send來跟蹤未完成的AJAX請求的數量。新的send()將基本上包裝設置爲onreadystatechange回調的內容,檢查readyState,根據需要遞增或遞減計數器,並調用原始回調函數。試圖跟蹤在Firefox中優秀的AJAX請求的數量

說我有似乎是一個特權問題,因爲如果我只是瀏覽一個網頁在一個正常的Firefox瀏覽器,打開Firebug,並在下面的代碼粘貼的問題,這似乎很好地工作:

document.ajax_outstanding = 0; 
if (typeof XMLHttpRequest.prototype.oldsend != 'function') { 
    XMLHttpRequest.prototype.oldsend = XMLHttpRequest.prototype.send; 
    XMLHttpRequest.prototype.send = function() { 
     console.log('in new send'); 
     console.log('this.onreadystatechange = ' + this.onreadystatechange); 
     this.oldonreadystatechange = this.onreadystatechange; 
     this.onreadystatechange = function() { 
      if (this.readyState == 2) { 
       /* LOADED */ 
       document.ajax_outstanding++; 
       console.log('set ajax_outstanding to ' + document.ajax_outstanding); 
      } 
      this.oldonreadystatechange.handleEvent.apply(this, arguments); 
      if (this.readyState == 4) { 
       /* COMPLETED */ 
       document.ajax_outstanding--; 
       console.log('set ajax_outstanding to ' + document.ajax_outstanding); 
      } 
     }; 
     this.oldsend.apply(this, arguments); 
    }; 
} 

現在,如果我使用的片斷的輕微修改後的版本從Greasemonkey的用戶腳本中,像這樣:

unsafeWindow.document.ajax_outstanding = 0; 
if (typeof unsafeWindow.XMLHttpRequest.prototype.oldsend != 'function') { 
    unsafeWindow.XMLHttpRequest.prototype.oldsend = unsafeWindow.XMLHttpRequest.prototype.send; 
    unsafeWindow.XMLHttpRequest.prototype.send = function() { 
     GM_log('in new send'); 
     GM_log('this.onreadystatechange = ' + this.onreadystatechange); 
     this.oldonreadystatechange = this.onreadystatechange; 
     this.onreadystatechange = function() { 
      if (this.readyState == 2) { 
       /* LOADED */ 
       unsafeWindow.document.ajax_outstanding++; 
       GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); 
      } 
      this.oldonreadystatechange.handleEvent.apply(this, arguments); 
      if (this.readyState == 4) { 
       /* COMPLETED */ 
       unsafeWindow.document.ajax_outstanding--; 
       GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); 
      } 
     }; 
     this.oldsend.apply(this, arguments); 
    }; 
} 

,我去一個網頁,做一些事情,使一個AJAX請求,我得到以下信息在javascript錯誤控制檯中:

http://www.blah.com/gmscripts/overrides: in new send 
uncaught exception: [Exception... "Illegal value" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: file:///tmp/customProfileDir41e7266f56734c97a2ca02b1f7f528e1/extensions/%7Be4a8a97b-f2ed-450b-b12d-ee082ba24781%7D/components/greasemonkey.js :: anonymous :: line 372" data: no] 

所以它似乎試圖訪問this.onreadystatechange

想必時要拋出異常,這是由於沙箱環境。 任何幫助將不勝感激。我沒有與此解決方案綁定,因此歡迎任何其他建議來執行我所需的操作。這只是我嘗試了其他幾個人,這似乎是最有前途的。要求是我需要確保在之後計數器達到0 readyState變爲4並且onreadystatechange回調完成執行。

回答

1

我最終使用下列內容:

unsafeWindow.document.ajax_outstanding = 0; 
if (typeof unsafeWindow.XMLHttpRequest.prototype.oldsend != 'function') { 
    unsafeWindow.XMLHttpRequest.prototype.oldsend = unsafeWindow.XMLHttpRequest.prototype.send; 
    unsafeWindow.XMLHttpRequest.prototype.send = function() { 
     unsafeWindow.XMLHttpRequest.prototype.oldsend.apply(this, arguments); 
     this.addEventListener('readystatechange', function() { 
      if (this.readyState == 2) { 
       /* LOADED */ 
       unsafeWindow.document.ajax_outstanding++; 
       console.log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); 
      } else if (this.readyState == 4) { 
       /* COMPLETED */ 
       unsafeWindow.document.ajax_outstanding--; 
       console.log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); 
      } 
     }, false); 
    }; 
} 
3

我做自己的東西:http://jsfiddle.net/rudiedirkx/skp28agx/(更新2015年1月22日)

腳本(應別的之前運行):

(function(xhr) { 
    xhr.active = 0; 
    var pt = xhr.prototype; 
    var _send = pt.send; 
    pt.send = function() { 
     xhr.active++; 
     this.addEventListener('readystatechange', function(e) { 
      if (this.readyState == 4) { 
       setTimeout(function() { 
        xhr.active--; 
       }, 1); 
      } 
     }); 
     _send.apply(this, arguments); 
    } 
})(XMLHttpRequest); 

而jsFiddle的測試腳本:

window.onload = function() { 
    var btn = document.querySelector('button'), 
     active = btn.querySelector('span'); 

    btn.onclick = function() { 
     // jQuery for easy ajax. `delay` is a jsFiddle argument 
     // to keep some requests active longer. 
     jQuery.post('/echo/json/', { 
      delay: Math.random() * 3, 
     }); 
    }; 

    updateActive(); 

    function updateActive() { 
     active.textContent = XMLHttpRequest.active; 
     requestAnimationFrame(updateActive); 
    } 
}; 

它更新每個動畫幀(〜每秒60次)按鈕中的計數器,與AJAX請求分開。無論你做什麼,無論多麼快速,你點擊它,計數器應該在幾秒鐘後總是以0結束。

+4

你真的給了本地主機地址還是我的眼睛? =)) – 2010-12-10 18:24:12

+0

請注意,對XMLHttpRequest.send的這種修改需要在發送任何AJAX請求之前安裝,否則計數器可能會出錯。另外,我認爲在調用'this._onreadystatechange'之後遞減'active'可能會更好(如果您認爲某個請求在其事件處理程序結束之前處於活動狀態)。 – seanf 2015-01-22 07:57:19