Ambil API vs XMLHttpRequest

163

Saya tahu bahwa Ambil API menggunakan Promises dan keduanya memungkinkan Anda untuk melakukan permintaan AJAX ke server.

Saya telah membaca bahwa Fetch API memiliki beberapa fitur tambahan, yang tidak tersedia di XMLHttpRequest(dan dalam polyfill API Fetch, karena didasarkan pada XHR).

Apa kemampuan tambahan yang dimiliki API Ambil?

ilyabasiuk
sumber
2
Meskipun saya tidak dapat mengingat di tempat, ada satu atau dua hal yang dapat Anda lakukan dengan XHR yang tidak dapat Anda ambil. Anda mengatakan Anda telah membaca bahwa mengambil memiliki kemungkinan tambahan, artikel-artikel itu tidak terlalu bagus jika mereka tidak mengatakan apa itu
Jaromanda X
2
menemukan dua hal yang tidak dapat Anda lakukan dengan mengambil yang Anda dapat dengan XHR ... Anda tidak dapat menetapkan nilai Anda sendiri untuk batas waktu permintaan dalam pengambilan, juga tidak bisa mendapatkan acara kemajuan
Jaromanda X
3
Ambil hanyalah cara yang disederhanakan dalam melakukan sesuatu untuk sebagian besar jenis XMLHttpRequests. Jika use case Anda cocok dengan apa yang Fetch lakukan, maka gunakanlah. Ketika Anda langsung turun ke sana XMLHttpRequest API jelek untuk apa kebanyakan orang menggunakannya. Fetch adalah upaya untuk menawarkan cara yang lebih bersih dalam melakukan hal-hal yang tidak memerlukan pustaka yang membungkus XMLHttpRequest untuk membuatnya enak.
jfriend00
1
Ini memiliki dukungan murni di browser ( caniuse.com/#search=fetch ), jadi ada polifill untuk itu github.com/github/fetch , yang bekerja di atas xhr
ilyabasiuk
4
@ Mars - Bagaimana Anda bisa mengatakan itu fetch(url).then(function(data) (...));tidak lebih sederhana daripada menggunakan XMLHttpRequestuntuk melakukan hal yang sama? Mungkin memiliki banyak fitur lain, tetapi ya ampun, itu jelas lebih mudah digunakan untuk hal-hal umum. Itu adalah API yang dibersihkan.
jfriend00

Jawaban:

120

Ada beberapa hal yang dapat Anda lakukan dengan mengambil dan tidak dengan XHR:

  • Anda dapat menggunakan API Cache dengan objek permintaan dan respons;
  • Anda dapat melakukan no-corspermintaan, mendapat respons dari server yang tidak menerapkan CORS. Anda tidak dapat mengakses badan tanggapan langsung dari JavaScript, tetapi Anda dapat menggunakannya dengan API lain (mis. API Cache);
  • Streaming tanggapan (dengan XHR seluruh respons buffered dalam memori, dengan mengambil Anda akan dapat mengakses aliran tingkat rendah). Ini belum tersedia di semua browser, tetapi akan segera.

Ada beberapa hal yang dapat Anda lakukan dengan XHR yang belum dapat Anda lakukan dengan mengambil, tetapi mereka akan tersedia cepat atau lambat (baca paragraf "Peningkatan masa depan" di sini: https: //hacks.mozilla .org / 2015/03 / this-api-is-so-fetching / ):

  • Batalkan permintaan (ini sekarang berfungsi di Firefox dan Edge, seperti yang dijelaskan @sontonbarker dalam komentarnya);
  • Laporkan kemajuan.

Artikel ini https://jakearchibald.com/2015/thats-so-fetch/ berisi deskripsi yang lebih rinci.

Marco
sumber
1
Spesifikasi untuk API Ambil sekarang menyediakan untuk pembatalan. Dukungan sejauh ini telah dikirim di Firefox 57 dan Edge 16. Demo: fetch-abort-demo-edge.glitch.me , mdn.github.io/dom-examples/abort-api . Dan ada bug terbuka Chrome & Webkit fitur bugs.chromium.org/p/chromium/issues/detail?id=750599 , bugs.webkit.org/show_bug.cgi?id=174980 . How-to: developers.google.com/web/updates/2017/09/abortable-fetch , developer.mozilla.org/en-US/docs/Web/API/AbortSignal#Examples . Dan contoh dalam jawaban Stack Overflow di stackoverflow.com/a/47250621/441757
sontonbarker
1
Perbedaan lainnya adalah bahwa fetchpermintaan tidak dapat diputar ulang di Alat Pengembang.
Parziphal
Dan, dari pengalaman saya, fetchdapat meminta file, tetapi XHR tidak bisa.
D. Pardal
64

mengambil

  • kehilangan metode bawaan untuk mengkonsumsi dokumen
  • ada cara untuk mengatur timeout belum
  • tidak dapat mengganti tajuk respons tipe konten
  • jika tajuk respons panjang konten ada tetapi tidak terbuka , panjang total tubuh tidak diketahui selama streaming
  • akan memanggil penangan abort sinyal meskipun permintaan telah selesai
  • tidak ada kemajuan unggahan (dukungan untuk ReadableStreaminstance karena badan permintaan belum datang )

XHR

  • tidak ada cara untuk tidak mengirim cookie (selain menggunakan bendera non-standarmozAnon atau AnonXMLHttpRequestkonstruktor)
  • tidak dapat mengembalikan FormDatainstance
  • tidak memiliki setara dengan fetch's no-corsmodus
  • selalu ikuti arahan ulang
Knu
sumber
13
fetchjuga tidak ada kemajuan. dengan XHR Anda dapat melacak kemajuan dengan progressacara tersebut
rzr
1
"tidak dapat mengganti header tipe konten dari respons" ... ini hanya ide yang buruk untuk memulai. tipe konten menentukan apa yang harus dikembalikan dan BACKEND HARUS menentukan itu ke frontend. SEBENARNYA, tipe konten harus menjadi 'HANYA HEADER' untuk jenis karena apa yang diminta, adalah apa yang harus dikembalikan. Jika Anda menginginkan sesuatu yang berbeda dari subdomain khusus atau sesuatu, maka Anda dapat menangani fungsionalitas tertentu secara terpisah. Anda mencoba untuk memaksa aturan 1% turun 99% dari tenggorokan everyones.
Orubel
@ Knu ya dan sekarang kami lebih maju dan kami dapat dengan mudah mengotomatiskan solusi 90% dan membiarkan case-freak ini merutekan ke fungsionalitas yang berbeda.
Orubel
1
@ rzr tidak persis, Anda mengerti Response#body.
Knu
9

Jawaban di atas baik dan memberikan wawasan yang baik, tetapi saya berbagi pendapat yang sama dengan yang dibagikan dalam entri blog pengembang google ini bahwa perbedaan utama (dari perspektif praktis) adalah kenyamanan janji bawaan yang dikembalikan darifetch

Alih-alih harus menulis kode seperti ini

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

function reqError(err) { ... }

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

kita dapat membersihkan dan menulis sesuatu yang lebih ringkas dan mudah dibaca dengan janji dan sintaksis modern

fetch('./api/some.json')
    .then((response) => {
        response.json().then((data) => { 
            ... 
        });
    })
    .catch((err) => { ... });
Felipe
sumber
8
@TheOpti Anda dapat melakukan polyfill basic fetch support ke IE 11. Anda juga bisa langsung menjatuhkan IE11 sebagai browser yang didukung di banyak proyek karena di banyak basis pengguna, penggunaan IE 11 sekarang di bawah 1%.
Devon Holcombe