Получить API против XMLHttpRequest

163

Я знаю, что Fetch API использует Promises, и оба они позволяют вам делать AJAX-запросы к серверу.

Я читал, что Fetch API имеет некоторые дополнительные функции, которые недоступны XMLHttpRequest(и в полизаполнении Fetch API, так как он основан на XHR).

Какие дополнительные возможности есть в Fetch API?

ilyabasiuk
источник
2
Хотя я не могу вспомнить на месте, есть одна или две вещи, которые вы можете сделать с XHR, которые вы не можете сделать с помощью fetch. Вы говорите, что читали, что у fetch есть дополнительные возможности, эти статьи не очень хороши, если они не говорят, что они есть
Jaromanda X
2
обнаружил две вещи, которые вы не можете сделать с извлечением, которые вы можете сделать с XHR ... вы не можете установить свое собственное значение для времени ожидания запроса в извлечении, а также не можете получать события прогресса
Jaromanda X
3
Fetch - это просто упрощенный способ выполнения задач для большинства типов запросов XMLHttp. Если ваш вариант использования соответствует тому, что делает Fetch, используйте его. Когда вы приступите прямо к этому, API-интерфейс XMLHttpRequest уродлив для того, для чего его использует большинство людей. Fetch была попыткой предложить более чистый способ выполнения задач, для которого не нужна библиотека, обернутая вокруг XMLHttpRequest, чтобы сделать ее приемлемой.
Jfriend00
1
Он имеет чистую поддержку в браузерах ( caniuse.com/#search=fetch ), так что для него есть полифилл github.com/github/fetch , который работает над xhr
ilyabasiuk
4
@ Марко - Как вы можете не сказать, что fetch(url).then(function(data) (...));это не проще, чем использовать XMLHttpRequestдля того же? У него может быть много других функций, но, черт возьми, его проще использовать для обычных вещей. Это очищенный API.
Jfriend00

Ответы:

120

Есть несколько вещей, которые вы можете сделать с fetch, а не с XHR:

  • Вы можете использовать Cache API с объектами запроса и ответа;
  • Вы можете выполнять no-corsзапросы, получая ответ от сервера, который не поддерживает CORS. Вы не можете получить доступ к телу ответа напрямую из JavaScript, но вы можете использовать его с другими API (например, Cache API);
  • Потоковые ответы (с помощью XHR весь ответ буферизируется в памяти, с помощью fetch вы сможете получить доступ к низкоуровневому потоку). Это доступно не во всех браузерах, но скоро будет.

С XHR вы можете сделать несколько вещей, которые вы еще не можете сделать с fetch, но они будут доступны рано или поздно (см. Параграф «Будущие улучшения» здесь: https: //hacks.mozilla .org / 2015/03 / это-то-то-самое-приятное / ):

  • Прервать запрос (теперь это работает в Firefox и Edge, как объясняет @sideshowbarker в своем комментарии);
  • Сообщить о прогрессе.

Эта статья https://jakearchibald.com/2015/thats-so-fetch/ содержит более подробное описание.

Marco
источник
1
Спецификация для Fetch API теперь предусматривает отмену. На данный момент поддержка поставляется в Firefox 57 и Edge 16. Демонстрации: fetch-abort-demo-edge.glitch.me , mdn.github.io/dom-examples/abort-api . И есть открытые ошибки в Chrome & Webkit bugs.chromium.org/p/chromium/issues/detail?id=750599 , bugs.webkit.org/show_bug.cgi?id=174980 . Практические рекомендации: developers.google.com/web/updates/2017/09/abortable-fetch , developer.mozilla.org/en-US/docs/Web/API/AbortSignal#Examples . И пример в ответ переполнением стека на stackoverflow.com/a/47250621/441757
sideshowbarker
1
Другое отличие состоит в том, что fetchзапросы не могут быть воспроизведены в Инструментах разработчика.
Parziphal
И, по моему опыту, fetchможет запросить файлы, но XHR не может.
Д. Пардал
64

получать

  • отсутствует встроенный метод для использования документов
  • нет возможности установить тайм - аут еще
  • не может переопределить заголовок ответа типа содержимого
  • если заголовок ответа на длину содержимого присутствует, но не доступен , общая длина тела неизвестна во время потоковой передачи
  • вызовет обработчик прерывания сигнала, даже если запрос был выполнен
  • нет прогресса загрузки (поддержка ReadableStreamэкземпляров, так как тела запросов еще впереди )

XHR

  • нет способа не отправлять куки (кроме использования нестандартного mozAnonфлага или AnonXMLHttpRequestконструктора)
  • не может вернуть FormDataэкземпляры
  • не имеет эквивалента для режима fetchsno-cors
  • всегда следовать перенаправлениям
Knu
источник
13
fetchтакже отсутствует прогресс. с XHR вы можете отслеживать прогресс с progressсобытием
rzr
1
«не могу переопределить заголовок типа содержимого ответа» ... это просто плохая идея для начала. тип содержимого диктует, что должно быть возвращено, и BACKEND ДОЛЖЕН указывать это внешнему интерфейсу. В действительности, тип контента должен быть «ЕДИНСТВЕННЫМ ЗАГОЛОМКОМ» для типа, потому что то, что запрашивается, это то, что должно быть возвращено. Если вы хотите что-то отличное от специального субдомена или чего-то еще, вы можете обрабатывать отдельные функции отдельно. Вы пытаетесь навязать правило 1% на 99% каждого горла.
Орубель
@Knu Да, и теперь мы более продвинуты, и мы можем легко автоматизировать 90% -ое решение и позволить странным случаям перейти на другую функциональность.
Орубель
1
@ rzr не совсем, вы получили Response#body.
Кну
9

Приведенные выше ответы являются хорошими и дают хорошее представление, но я разделяю то же мнение, что и в этой записи блога разработчиков Google, в том, что основное отличие (с практической точки зрения) заключается в удобстве встроенного обещания, возвращаемого изfetch

Вместо того, чтобы писать такой код

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

мы можем привести в порядок вещи и написать что-то более краткое и удобочитаемое с обещаниями и современным синтаксисом

fetch('./api/some.json')
    .then((response) => {
        response.json().then((data) => { 
            ... 
        });
    })
    .catch((err) => { ... });
Фелипе
источник
8
@TheOpti. Вы можете добавить в Poly 11. поддержку основных выборок в IE 11. Вы также можете просто отказаться от IE11 в качестве поддерживаемого браузера во многих проектах, поскольку во многих пользовательских базах использование IE 11 теперь ниже 1%.
Девон Холкомб