分享JavaScript監(jiān)聽全部Ajax請(qǐng)求事件的方法
若Ajax請(qǐng)求是由jQuery的$.ajax
發(fā)起的,默認(rèn)情況下可以使用 jQuery的Global Ajax Event Handlers監(jiān)聽到Ajax事件,然而我遇到的卻是用原生JavaScript發(fā)起的Ajax請(qǐng)求,所以這種方法行不通。
然后呢,還有其他方法,比如說 Pub/Sub,但是這個(gè)發(fā)起請(qǐng)求的 js 代碼我是無法改動(dòng)的,也就不存在向代碼里添加 publish 的問題。同理,jQuery 的 .bind
和 .trigger
也無法使用。
最后,決定使用直接 override XMLHttpRequest
,同時(shí)配合使用自定義事件。
在 StackOverflow 上搜索,發(fā)現(xiàn)有個(gè)歪果仁給出了一個(gè)不靠譜的解決方法,嗯,貼出來給大家看看:
;(function () { var open = window.XMLHttpRequest.prototype.open, send = window.XMLHttpRequest.prototype.send, onReadyStateChange; function openReplacement(method, url, async, user, password) { // some code return open.apply(this, arguments); } function sendReplacement(data) { // some code if(this.onreadystatechange) this._onreadystatechange = this.onreadystatechange; this.onreadystatechange = onReadyStateChangeReplacement; return send.apply(this, arguments); } function onReadyStateChangeReplacement() { // some code if (this._onreadystatechange) return this._onreadystatechange.apply(this, arguments); } window.XMLHttpRequest.prototype.open = openReplacement; window.XMLHttpRequest.prototype.send = sendReplacement; })();
這個(gè)解決方案,無法監(jiān)聽全部的 XHR Events
,而且 readystatechange
事件是在調(diào)用 send
方法后才監(jiān)聽,也就無法監(jiān)聽到 readyState = 1
時(shí)的事件。同時(shí),如果在使用 send
方法后再對(duì) onreadystatechange
設(shè)置回調(diào)函數(shù),會(huì)將 override
的代碼又一次 override
,也就無法產(chǎn)生預(yù)想的效果。
那如何才能正確地 override XHR 呢?貼上代碼,一起來看看:
;(function() { function ajaxEventTrigger(event) { var ajaxEvent = new CustomEvent(event, { detail: this }); window.dispatchEvent(ajaxEvent); } var oldXHR = window.XMLHttpRequest; function newXHR() { var realXHR = new oldXHR(); realXHR.addEventListener('abort', function () { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false); realXHR.addEventListener('error', function () { ajaxEventTrigger.call(this, 'ajaxError'); }, false); realXHR.addEventListener('load', function () { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false); realXHR.addEventListener('loadstart', function () { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false); realXHR.addEventListener('progress', function () { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false); realXHR.addEventListener('timeout', function () { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false); realXHR.addEventListener('loadend', function () { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false); realXHR.addEventListener('readystatechange', function() { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false); return realXHR; } window.XMLHttpRequest = newXHR; })();
這樣,就為 XHR
添加了自定義事件。如何調(diào)用?
var xhr = new XMLHttpRequest(); window.addEventListener('ajaxReadyStateChange', function (e) { console.log(e.detail); // XMLHttpRequest Object }); window.addEventListener('ajaxAbort', function (e) { console.log(e.detail.responseText); // XHR 返回的內(nèi)容 }); xhr.open('GET', 'info.json'); xhr.send();
需要注意的是,正常的 readystatechange
等事件 handler
返回的 e
是 XMLHttpRequest
對(duì)象,但是自定義方法 ajaxReadyStateChange
等事件 handler 返回的 e
是 CustomEvent
對(duì)象,而 e.detail
才是真正的 XMLHttpRequest
對(duì)象。而獲得 Ajax 請(qǐng)求返回內(nèi)容的 e.responseText
也需要修改為 e.detail.responseText
。
同時(shí),addEventListener
方法必須掛載在 window 對(duì)象
上,而不能是 XHR
實(shí)例上。
因?yàn)橐陨洗a使用了 CustomEvent
構(gòu)造函數(shù),在現(xiàn)代瀏覽器上可以正常使用,但是在 IE 下,甚至連 IE 11 都不支持,所以需要加上 Polyfill
,變成這樣:
;(function () { if ( typeof window.CustomEvent === "function" ) return false; function CustomEvent ( event, params ) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent( 'CustomEvent' ); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); return evt; } CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; })(); ;(function () { function ajaxEventTrigger(event) { var ajaxEvent = new CustomEvent(event, { detail: this }); window.dispatchEvent(ajaxEvent); } var oldXHR = window.XMLHttpRequest; function newXHR() { var realXHR = new oldXHR(); realXHR.addEventListener('abort', function () { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false); realXHR.addEventListener('error', function () { ajaxEventTrigger.call(this, 'ajaxError'); }, false); realXHR.addEventListener('load', function () { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false); realXHR.addEventListener('loadstart', function () { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false); realXHR.addEventListener('progress', function () { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false); realXHR.addEventListener('timeout', function () { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false); realXHR.addEventListener('loadend', function () { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false); realXHR.addEventListener('readystatechange', function() { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false); return realXHR; } window.XMLHttpRequest = newXHR; })();
此時(shí),就可以在 IE 9+、Chrome 15+、FireFox 11+、Edge、Safari 6.1+、Opera 12.1+ 上愉快地使用了,以上就是本文的全部?jī)?nèi)容,希望大家能夠喜歡。
- js每隔5分鐘執(zhí)行一次ajax請(qǐng)求的實(shí)現(xiàn)方法
- 詳解JavaScript for循環(huán)中發(fā)送AJAX請(qǐng)求問題
- html+js+php一次原始的Ajax請(qǐng)求示例
- JS 攔截全局ajax請(qǐng)求實(shí)例解析
- Javascript發(fā)送AJAX請(qǐng)求實(shí)例代碼
- JS Ajax請(qǐng)求如何防止重復(fù)提交
- 實(shí)例講解使用原生JavaScript處理AJAX請(qǐng)求的方法
- php ajax數(shù)據(jù)傳輸和響應(yīng)方法
- thinkphp中ajax與php響應(yīng)過程詳解
- 原生javascript的ajax請(qǐng)求及后臺(tái)PHP響應(yīng)操作示例
相關(guān)文章
JavaScript EventEmitter 背后的秘密 完整版
在這里,我們的目標(biāo)創(chuàng)建屬于我們自己的 Event Emitter 去理解背后的秘密。所以,讓我們看一下下面的代碼是怎么工作的,需要的朋友可以參考下2018-03-03JavaScript實(shí)現(xiàn)星星等級(jí)評(píng)價(jià)功能
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)星星等級(jí)評(píng)價(jià)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03JavaScript es6中var、let以及const三者區(qū)別案例詳解
這篇文章主要介紹了JavaScript es6中var、let以及const三者區(qū)別案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08js定時(shí)器怎么寫?就是在特定時(shí)間執(zhí)行某段程序
定時(shí)器想必大家并不陌生吧,在本文為大家詳細(xì)介紹下js中是如何實(shí)現(xiàn)定時(shí)器的,具體原理及代碼如下,感興趣的朋友不要錯(cuò)過2013-10-10請(qǐng)求時(shí)token過期自動(dòng)刷新token操作
這篇文章主要介紹了請(qǐng)求時(shí)token過期自動(dòng)刷新token操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09JS 動(dòng)態(tài)判斷PC和手機(jī)瀏覽器實(shí)現(xiàn)代碼
這篇文章主要介紹了JS 動(dòng)態(tài)判斷PC和手機(jī)瀏覽器實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-09-09