หากคำขอ AJAX เริ่มต้นด้วย $.ajax ของ JQuery โดยค่าเริ่มต้นคุณสามารถใช้ตัวจัดการเหตุการณ์ AJAX ของ JQuery เพื่อฟังเหตุการณ์ AJAX อย่างไรก็ตามสิ่งที่ฉันพบคือคำขอ AJAX ที่เริ่มต้นด้วย JavaScript ดั้งเดิมดังนั้นวิธีนี้ไม่ทำงาน
จากนั้นมีวิธีการอื่น ๆ เช่น Pub/Sub แต่ฉันไม่สามารถเปลี่ยนรหัส JS ที่เริ่มต้นคำขอได้ดังนั้นจึงไม่มีปัญหาในการเพิ่มการเผยแพร่ลงในรหัส ในทำนองเดียวกันไม่สามารถใช้ .bind เกอร์และ .trigger ได้
ในที่สุดฉันตัดสินใจที่จะใช้ override XMLHttpRequest โดยตรงในขณะที่ใช้กิจกรรมที่กำหนดเอง
การค้นหา stackoverflow ฉันพบว่าคนเลวหนึ่งคนให้ทางออกที่ไม่น่าเชื่อถือ ฉันจะโพสต์ให้คุณดู:
; (function () {var open = window.xmlhttprequest.prototype.open, send = window.xmlhttprequest.prototype.send, onreadystatechange; ฟังก์ชั่น openreplacement (วิธีการ, url, async, ผู้ใช้, รหัสผ่าน) if (this.onreadystatechange) this._onreadystatechange = this.onreadystatechange; window.xmlhttprequest.prototype.open = openreplacement; โซลูชันนี้ไม่สามารถฟัง XHR Events ทั้งหมดและเหตุการณ์ readystatechange จะถูกฟังหลังจากเรียกใช้วิธี send เท่านั้นดังนั้นจึงไม่สามารถฟังเหตุการณ์เมื่อ readyState = 1 ในเวลาเดียวกันหากคุณตั้งค่าฟังก์ชั่นการโทรกลับสำหรับ onreadystatechange หลังจากใช้วิธี send รหัส override override อีกครั้งและจะไม่เกิดผลที่คาดหวัง
แล้วฉันจะแทนที่ XHR ได้อย่างถูกต้องได้อย่างไร? โพสต์รหัสแล้วลองดู:
; (function () {function ajaxeventtrigger (เหตุการณ์) {var ajaxevent = new customevent (เหตุการณ์, {รายละเอียด: this}); window.dispatchevent (ajaxevent);} var oldxhr = window.xmlhttprequest; realxhr.addeventListener ('abort', function () {ajaxeventtrigger.call (นี่, 'ajaxabort');}, false); realxhr.addeventListener ('load', function () {ajaxeventtrigger.call (นี่, 'ajaxload');}, false); realxhr.addeventListener ('หมดเวลา', function () {ajaxeventtrigger.call (นี่, 'ajaxtimeout');}, false); realxhr.addeventListener ('ReadyStateChange', function () {AjaxeventTrigger.Call (นี่, 'AJAXREADSTATECHANGE');}, FALSE); ด้วยวิธีนี้จะมีการเพิ่มเหตุการณ์ที่กำหนดเองใน XHR โทรหาอย่างไร?
var xhr = ใหม่ xmlhttprequest (); window.addeventListener ('ajaxreadystatechange', ฟังก์ชั่น (e) {console.log (e.detail); // xmlhttprequest Object}); window.addeventListener ('ajaxabort', ฟังก์ชั่น (e) {console.log (e.detail.responsetext); // เนื้อหาที่ส่งคืนโดย xhr}); xhr.open ('get', 'info.json'); xhr.send (); ควรสังเกตว่า e ที่ส่งคืนโดย readystatechange ปกติและ handler เหตุการณ์อื่น ๆ คือวัตถุ XMLHttpRequest แต่ e ที่ส่งคืนโดยวิธีการที่กำหนดเอง ajaxReadyStateChange และตัวจัดการเหตุการณ์อื่น ๆ เป็นวัตถุ e.detail CustomEvent XMLHttpRequest e.responseText ที่ได้รับเนื้อหาที่ส่งคืนโดยคำขอ AJAX จะต้องมีการแก้ไขเป็น e.detail.responseText
ในเวลาเดียวกันจะต้องติดตั้งวิธี addEventListener บน window 对象ไม่ใช่ในอินสแตนซ์ XHR
เนื่องจากรหัสด้านบนใช้ตัวสร้าง CustomEvent จึงสามารถใช้งานได้ตามปกติในเบราว์เซอร์ที่ทันสมัย แต่ภายใต้ IE แม้กระทั่ง IE 11 ไม่รองรับดังนั้นจึงจำเป็นต้องเพิ่ม Polyfill และมันจะกลายเป็นเช่นนี้:
; (function () {if (typeof window.customevent === "function") return false; ฟังก์ชั่น contivityEvent (เหตุการณ์, params) {params = params || {bubbles: false, cancelable: false, รายละเอียด: undefined}; var evt = document.create params.detail); return evt;} customevent.prototype = window.event.prototype; window.xmlhttprequest; ฟังก์ชั่น newxhr () {var realxhr = oldxhr ใหม่ (); ajaxeventtriger.call (นี่คือ 'ajaxerror'); 'ajaxloadstart'); }, false); realxhr.addeventListener ('หมดเวลา', ฟังก์ชั่น () {ajaxeventtrigger.call (นี่, 'ajaxtimeout');}, false); realxhr.addeventListener ('ReadyStateChange', function () {AjaxeventTrigger.Call (นี่, 'AJAXREADSTATECHANGE');}, FALSE);ในเวลานี้คุณสามารถใช้อย่างมีความสุขกับ IE 9+, Chrome 15+, Firefox 11+, Edge, Safari 6.1+ และ Opera 12.1+ ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าคุณจะชอบมัน