Farklı JS kitaplıkları tarafından yapılan tüm AJAX isteklerine nasıl müdahale edilir


110

Farklı JS kitaplıklarına (AngularJS, OpenLayers, ...) sahip bir web uygulaması oluşturuyorum ve günlüğe kaydedilen kullanıcı oturumunun sona ermesi durumunda (yanıt 401 Unauthorizeddurumla birlikte geri gelir ), onu yeniden yönlendirmek için tüm AJAX yanıtlarını yakalamanın bir yoluna ihtiyacım var giriş sayfasına.

AngularJS'nin interceptorsbu tür senaryoları yönetmeyi teklif ettiğini biliyorum , ancak OpenLayers isteklerine bu tür bir enjeksiyon gerçekleştirmenin bir yolunu bulamadım. Bu yüzden vanilya JS yaklaşımını tercih ettim.

İşte bu kod parçasını buldum ...

(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);

... uyarladığım ve beklendiği gibi davrandığını gördüm (yalnızca son Google Chrome'da test etti).

XMLHTTPRequest'in prototipini değiştirirken, bunun ne kadar tehlikeli sonuçlanabileceğini veya ciddi performans sorunlarına yol açıp açmayacağını merak ediyorum. Ve bu arada geçerli bir alternatif olabilir mi?

Güncelleme: İstekler gönderilmeden önce nasıl müdahale edilir?

Önceki numara iyi çalışıyor. Peki ya aynı senaryoda, istek gönderilmeden önce bazı başlıklar eklemek isterseniz? Aşağıdakileri yapın:

(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);

4
Bana tamamen güvenli görünüyor.
barmar

Tek performans etkisi, her AJAX yanıtı sırasında ekstra bir işlev çalıştırmasıdır, ancak yapmak istediğiniz şey budur.
barmar

bunun gibi bir şey arıyordum. çok teşekkürler
Silver Moon

Yanıtlar:


36

Bu tür işlev kancalama tamamen güvenlidir ve başka nedenlerle diğer yöntemlerde düzenli olarak yapılır.

Ve tek performans etkisi, gerçekten her biri için fazladan bir işlev çağrısı ve .open()kendi başınıza çalıştırdığınız koddur ve bu, bir ağ çağrısı söz konusu olduğunda muhtemelen önemsizdir.


IE'de bu, ActiveXObjectAjax yapmanın kontrol yöntemini kullanmaya çalışan herhangi bir kodu yakalamaz . İyi yazılmış kod önce XMLHttpRequestnesneyi arar ve eğer varsa ve IE 7'den beri ActiveXObjectmevcutsa onu kullanır. Ancak, eğer mevcutsa yöntemi kullanan ve IE'nin daha sonraki sürümlerinde doğru olabilecek bazı kodlar olabilir .


Modern tarayıcılarda, fetch()arayüz gibi Ajax çağrılarını yayınlamanın başka yolları da vardır; bu nedenle, tüm Ajax çağrılarını bağlamak istiyorsanız, sadece daha fazlasını bağlamanız gerekir XMLHttpRequest.


1
Merhaba @ jfriend00 - tüm api isteklerini nasıl bağlarsınız - stackoverflow.com/questions/44728723/… ?
colemerrick

1
@bagofcole - Muhtemelen, fetch()tüm çağrıları engellemek için işlevi maymunla yama yapabilirsiniz - gerçi ben bunu hiç denemedim. Görünüşe göre bu modül bunu yapıyor.
jfriend00

comment_service_ajaxİstekleri çekmeye çalışırken YouTube'u bozar.
Leeroy

3

Bu, IE'nin bazı sürümleri için (9 ve altı) XMLHttpRequests'i yakalayamaz . Kitaplığa bağlı olarak, önce IE'nin tescilli ActiveX denetimini arayabilirler.

Ve elbette, IE altında katı olmayan bir DOCTYPE kullanıyorsanız tüm bahisler kapalıdır, ancak bunu bildiğinizden eminim.

Referans: CanIuse


2

Firefox AMO Editor tarafından nazikçe belirtildiği gibi Rob W,

Aşağıdaki kod, XMLHttpRequest davranışını değiştirir. Varsayılan olarak, üçüncü ("zaman uyumsuz") parametre belirtilmezse, varsayılan olarak true olur. Belirtildiğinde ve tanımsız olduğunda, eşzamanlı bir HTTP isteğinde bir isteği döndüren "false" ile eşdeğerdir. Bu, istek işlenirken kullanıcı arayüzünün engellenmesine neden olur ve XMLHttpRequest API'sinin bazı özellikleri de devre dışı bırakılır.

...

Bunu düzeltmek için open.call (....) yerine open.apply (this, arguments) yazın;

Ve işte bir referans bağlantısı:

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


("Aşağıdaki kod", sorudaki pasajı ifade eder)
Rob W
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.