Getir() işlevine giriş

fetch() API'si pencere nesnesine iniyor ve XHR'leri değiştirmek istiyor

Matt Gaunt

Çok uzun XMLHttpRequest

fetch(), XMLHttpRequest (XHR) benzeri ağ istekleri oluşturmanıza olanak tanır. Temel fark, Fetch API'sinin Promises kullanmasıdır. Promises, daha basit ve temiz bir API sağlar. Böylece geri çağırma cehennemini ortadan kaldırır ve XMLHttpRequest'in karmaşık API'sini hatırlamak zorunda kalmaz.

Tarayıcı Desteği

  • 42
  • 14
  • 39
  • 10.1

Kaynak

Getirme API'si, Chrome 40'tan beri Service Worker küresel kapsamında kullanılabilmektedir, ancak Chrome 42'de pencere kapsamında etkinleştirilecektir. Ayrıca, bugün kullanabileceğiniz bir de GitHub tarafından geliştirilen çoklu dolgu özelliği var.

Promise'i daha önce kullanmadıysanız JavaScript Promise'lere Giriş konusuna göz atın.

Temel Getirme İsteği

XMLHttpRequest ve ardından fetch ile uygulanan basit bir örneği karşılaştırarak başlayalım. Yalnızca bir URL istemek, yanıt almak ve bunu JSON olarak ayrıştırmak istiyoruz.

XMLHttpRequest

XMLHttpRequest, başarı ve hata durumlarını ele almak için iki işleyicinin ayarlanmasına ve open() ile send() çağrılarına ihtiyaç duyar. MDN dokümanlarından örnek.

function reqListener() {
    var data = JSON.parse(this.responseText);
    console.log(data);
}

function reqError(err) {
    console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

Getirme

Getirme isteğimizin görünümü aşağıdaki gibidir:

fetch('./api/some.json')
    .then(
    function(response) {
        if (response.status !== 200) {
        console.log('Looks like there was a problem. Status Code: ' +
            response.status);
        return;
        }

        // Examine the text in the response
        response.json().then(function(data) {
        console.log(data);
        });
    }
    )
    .catch(function(err) {
    console.log('Fetch Error :-S', err);
    });

Yanıtı JSON olarak ayrıştırmadan önce yanıt durumunun 200 olup olmadığını kontrol ederek başlarız.

fetch() isteğinin yanıtı bir Stream nesnesidir. Bu, akışın okunması eşzamansız olarak gerçekleştiğinden json() yöntemini çağırdığımızda bir Promise döndürülür.

Yanıt Meta Verileri

Önceki örnekte, Response nesnesinin durumunu ve yanıtın JSON olarak nasıl ayrıştırılacağını inceledik. Üstbilgiler gibi erişmek isteyebileceğimiz diğer meta veriler aşağıda gösterilmiştir.

fetch('users.json').then(function(response) {
    console.log(response.headers.get('Content-Type'));
    console.log(response.headers.get('Date'));

    console.log(response.status);
    console.log(response.statusText);
    console.log(response.type);
    console.log(response.url);
});

Yanıt Türleri

Bir getirme isteğinde bulunduğumuzda yanıt olarak response.type "basic", "cors" veya "opaque" verilir. Bu types, kaynağın nereden geldiğini gösterir ve yanıt nesnesini nasıl ele almanız gerektiğini bildirmek için kullanılabilir.

Aynı kaynaktaki bir kaynak için istekte bulunulduğunda, yanıt basic türünde olur ve yanıttan neleri görüntüleyebileceğinizle ilgili herhangi bir kısıtlama uygulanmaz.

COR üst bilgilerini döndüren başka bir kaynaktaki bir kaynak için istek yapılırsa tür cors olur. cors ve basic yanıtları neredeyse aynıdır. Tek fark, cors yanıtının görüntüleyebileceğiniz başlıkları Cache-Control, Content-Language, Content-Type, Expires, Last-Modified ve Pragma ile kısıtlamasıdır.

opaque yanıtı, CORS üst bilgileri döndürmeyen farklı bir kaynaktaki bir kaynak için yapılan istek içindir. Opak bir yanıt kullanıldığında, döndürülen verileri okuyamayız veya isteğin durumunu görüntüleyemeyiz. Diğer bir deyişle, isteğin başarılı olup olmadığını kontrol edemeyiz.

Bir getirme isteği için yalnızca belirli isteklerin çözümleneceği bir mod tanımlayabilirsiniz. Ayarlayabileceğiniz modlar şunlardır:

  • same-origin yalnızca aynı kaynaktaki öğe istekleri için başarılı olur, diğer tüm istekler reddedilir.
  • cors, uygun COR üst bilgilerini döndüren aynı kaynak ve diğer kaynaklardaki öğe isteklerine izin verir.
  • cors-with-forced-preflight, gerçek istekte bulunmadan önce her zaman ön kontrol gerçekleştirir.
  • no-cors, CORS başlıkları olmayan ve opaque yanıtıyla sonuçlanan diğer kaynaklara istek göndermek için tasarlanmıştır ancak belirtildiği gibi, bu işlem şu anda pencere global kapsamında mümkün değildir.

Modu tanımlamak için fetch isteğindeki ikinci parametre olarak bir options nesnesi ekleyin ve bu nesnede modu tanımlayın:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
    .then(function(response) {
    return response.text();
    })
    .then(function(text) {
    console.log('Request successful', text);
    })
    .catch(function(error) {
    log('Request failed', error)
    });

Zincirleme Sözler

Vaatlerin en iyi özelliklerinden biri bunları bir araya getirebilme olanağıdır. Getirme için bu, mantığı getirme istekleri arasında paylaşmanıza olanak tanır.

Bir JSON API ile çalışıyorsanız durumu kontrol etmeniz ve her yanıt için JSON'u ayrıştırmanız gerekir. Vaat döndüren ayrı işlevlerde durumu ve JSON ayrıştırmasını tanımlayarak kodunuzu basitleştirebilirsiniz. Böylece yalnızca nihai verileri ve hata durumunu ele alma konusunda endişelenmenize gerek kalmaz.

function status(response) {
    if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
    } else {
    return Promise.reject(new Error(response.statusText))
    }
}

function json(response) {
    return response.json()
}

fetch('users.json')
    .then(status)
    .then(json)
    .then(function(data) {
    console.log('Request succeeded with JSON response', data);
    }).catch(function(error) {
    console.log('Request failed', error);
    });

response.status özelliğini kontrol eden ve çözümlenen veya reddedilen bir Promise döndüren Promise.resolve() veya Promise.reject() sonucunu döndüren status işlevini tanımlarız. Bu, fetch() zincirimizde adı verilen ilk yöntemdir. Sorun çözülürse daha sonra response.json() çağrısından yine bir Promise döndüren json() yöntemimizi çağırırız. Bunun ardından, ayrıştırılan JSON'dan bir nesnemiz olur. Ayrıştırma başarısız olursa Promise reddedilir ve yakalama ifadesi yürütülür.

Bunun en iyi tarafı, mantığı tüm getirme istekleriniz arasında paylaşabilmenizdir. Böylece, kodun bakımını, okunmasını ve test edilmesini kolaylaştırırsınız.

POST İsteği

Web uygulamalarının POST yöntemiyle bir API'yi çağırmaları ve isteğin gövdesine bazı parametreleri sağlamaları çok normaldir.

Bunu yapmak için fetch() seçeneklerinde method ve body parametrelerini ayarlayabiliriz.

fetch(url, {
    method: 'post',
    headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
    })
    .then(json)
    .then(function (data) {
    console.log('Request succeeded with JSON response', data);
    })
    .catch(function (error) {
    console.log('Request failed', error);
    });

Getirme İsteğiyle Kimlik Bilgileri Gönderme

Çerezler gibi kimlik bilgileriyle bir getirme isteğinde bulunmak isterseniz isteğin credentials değerini "include" olarak ayarlamanız gerekir.

fetch(url, {
    credentials: 'include'
})

SSS

Bir fetch() isteğini nasıl iptal ederim?

Şu anda getirme işlemini iptal etmenin bir yolu yoktur, ancak bu durum GitHub'da ele alınmaktadır. Bu bağlantı için @jaffathecake adresine e-posta gönderin.

Çoklu dolgu var mı?

GitHub'da getirme işlemi için bir çoklu dolgu bulunur. H/T @Nexii'ye dikkat çekmek istiyorum.

Neden Service Worker'larda "no-cors" desteklenirken pencerede desteklenmiyor?

Bu durum, güvenlikle ilgili bir sorundan kaynaklanmaktadır. Buradan daha fazla bilgi edinebilirsiniz.