Cara mencegat semua permintaan AJAX yang dibuat oleh pustaka JS berbeda

110

Saya sedang membangun aplikasi web dengan pustaka JS yang berbeda (AngularJS, OpenLayers, ...) dan membutuhkan cara untuk mencegat semua tanggapan AJAX agar dapat, jika sesi pengguna yang dicatat kedaluwarsa (tanggapan kembali dengan 401 Unauthorizedstatus), untuk mengarahkannya ke halaman login.

Saya tahu AngularJS menawarkan interceptorsuntuk mengelola skenario seperti itu, tetapi tidak dapat menemukan cara untuk mencapai injeksi seperti itu ke dalam permintaan OpenLayers. Jadi saya memilih pendekatan vanilla JS.

Di sini saya menemukan potongan kode ini ...

(function(open) {

    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

        this.addEventListener("readystatechange", function() {
            console.log(this.readyState); // this one I changed
        }, false);

        open.call(this, method, url, async, user, pass);
    };

})(XMLHttpRequest.prototype.open);

... yang saya adaptasi dan sepertinya berperilaku seperti yang diharapkan (hanya mengujinya di Google Chrome terakhir).

Karena memodifikasi prototipe XMLHTTPRequest, saya bertanya-tanya seberapa berbahaya hal ini dapat terjadi atau jika dapat menghasilkan masalah kinerja yang serius. Dan apakah akan ada alternatif yang valid?

Pembaruan: cara mencegat permintaan sebelum dikirim

Trik sebelumnya bekerja dengan baik. Tetapi bagaimana jika dalam skenario yang sama Anda ingin memasukkan beberapa header sebelum permintaan dikirim? Lakukan hal berikut:

(function(send) {

    XMLHttpRequest.prototype.send = function(data) {

        // in this case I'm injecting an access token (eg. accessToken) in the request headers before it gets sent
        if(accessToken) this.setRequestHeader('x-access-token', accessToken);

        send.call(this, data);
    };

})(XMLHttpRequest.prototype.send);
mettjus
sumber
4
Sepertinya sangat aman bagi saya.
Barmar
Satu-satunya dampak kinerja adalah ia akan menjalankan fungsi tambahan selama setiap respons AJAX, tetapi itulah yang ingin Anda lakukan.
Barmar
saya sedang mencari sesuatu seperti ini. terima kasih banyak
Silver Moon

Jawaban:

36

Jenis pengait fungsi ini sangat aman dan dilakukan secara teratur dengan metode lain karena alasan lain.

Dan, satu-satunya dampak kinerja hanyalah satu panggilan fungsi tambahan untuk masing-masing .open()ditambah kode apa pun yang Anda jalankan sendiri yang mungkin tidak penting ketika panggilan jaringan terlibat.


Di IE, ini tidak akan menangkap kode apa pun yang mencoba menggunakan ActiveXObjectmetode kontrol untuk melakukan Ajax. Kode yang ditulis dengan baik pertama-tama mencari XMLHttpRequestobjek dan menggunakannya jika tersedia dan yang telah tersedia sejak IE 7. Tetapi, mungkin ada beberapa kode yang menggunakan ActiveXObjectmetode tersebut jika tersedia yang akan benar melalui versi IE yang lebih baru.


Di browser modern, ada cara lain untuk mengeluarkan panggilan Ajax seperti fetch()antarmuka jadi jika seseorang ingin menghubungkan semua panggilan Ajax, Anda harus menghubungkan lebih dari sekadar XMLHttpRequest.

jfriend00
sumber
1
Hai @ jfriend00 - bagaimana Anda akan menghubungkan semua permintaan api pengambilan - stackoverflow.com/questions/44728723/… ?
colemerrick
1
@ bagofcole - Anda mungkin bisa menambal fetch()fungsi untuk mencegat semua panggilan ke sana - meskipun saya sendiri belum pernah mencobanya. Sepertinya modul ini melakukan itu.
jfriend00
Menghancurkan YouTube saat mencoba menarik comment_service_ajaxpermintaan.
Leeroy
3

Ini tidak akan menangkap XMLHttpRequests untuk beberapa versi IE (9 dan di bawahnya) . Bergantung pada pustaka, mereka mungkin mencari kontrol ActiveX milik IE terlebih dahulu.

Dan, tentu saja, semua taruhan dibatalkan jika Anda menggunakan DOCTYPE yang tidak ketat di bawah IE, tetapi saya yakin Anda tahu itu.

Referensi: CanIuse

Jeremy J Starcher
sumber
2

Seperti yang ditunjukkan oleh Firefox AMO Editor Rob W,

Kode berikut mengubah perilaku XMLHttpRequest. Secara default, jika parameter ketiga ("async") tidak ditentukan, defaultnya adalah true. Jika ditentukan dan tidak ditentukan, ini setara dengan "false", yang mengubah permintaan menjadi permintaan HTTP sinkron. Hal ini menyebabkan UI memblokir saat permintaan sedang diproses, dan beberapa fitur API XMLHttpRequest juga dinonaktifkan.

...

Untuk memperbaikinya, ganti open.call (....) dengan open.apply (this, arguments);

Dan berikut ini tautan referensi:

https://xhr.spec.whatwg.org/#the-open()-method

Walty Yeung
sumber
(di mana "Kode berikut" mengacu pada potongan dari pertanyaan)
Rob W