Введение в выборку()

API fetch() размещается в объекте окна и пытается заменить XHR.

Прощай, XMLHttpRequest.

fetch() позволяет отправлять сетевые запросы, аналогичные XMLHttpRequest (XHR). Основное отличие состоит в том, что API-интерфейс Fetch использует Promises, что позволяет использовать более простой и понятный API, избегая ада обратных вызовов и необходимости запоминать сложный API XMLHttpRequest.

Поддержка браузера

  • 42
  • 14
  • 39
  • 10.1

Источник

Fetch API доступен в глобальной области Service Worker начиная с Chrome 40, но в Chrome 42 он будет включен в области окна. Существует также довольно интересный полифил от GitHub , который вы можете использовать сегодня.

Если вы никогда раньше не использовали Promises , ознакомьтесь со статьей «Введение в промисы JavaScript» .

Базовый запрос на получение

Давайте начнем со сравнения простого примера, реализованного с помощью XMLHttpRequest , а затем с помощью fetch . Мы просто хотим запросить URL-адрес, получить ответ и проанализировать его как JSON.

XMLHttpRequest

Для XMLHttpRequest потребуется настроить два прослушивателя для обработки случаев успеха и ошибки, а также вызов open() и send() . Пример из документации MDN .

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

Принести

Наш запрос на выборку выглядит примерно так:

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

Мы начинаем с проверки того, что статус ответа равен 200, прежде чем анализировать ответ как JSON.

Ответом на запрос fetch() является объект Stream , а это означает, что когда мы вызываем метод json() , возвращается Promise, поскольку чтение потока будет происходить асинхронно.

Метаданные ответа

В предыдущем примере мы рассмотрели состояние объекта Response , а также то, как анализировать ответ как JSON. Другие метаданные, к которым мы можем захотеть получить доступ, например заголовки, показаны ниже.

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

Типы ответов

Когда мы делаем запрос на выборку, ответу будет присвоен response.type « basic », « cors » или « opaque ». Эти types указывают, откуда взялся ресурс, и могут использоваться для информирования о том, как следует обращаться с объектом ответа.

Когда делается запрос к ресурсу из того же источника, ответ будет иметь basic тип, и нет никаких ограничений на то, что вы можете просмотреть из ответа.

Если делается запрос на ресурс из другого источника, который возвращает заголовки COR , то типом является cors . cors и basic ответы практически идентичны, за исключением того, что ответ cors ограничивает заголовки, которые вы можете просматривать, Cache-Control , Content-Language , Content-Type , Expires , Last-Modified и Pragma .

opaque ответ предназначен для запроса ресурса из другого источника, который не возвращает заголовки CORS. При непрозрачном ответе мы не сможем прочитать возвращенные данные или просмотреть статус запроса, то есть мы не сможем проверить, был ли запрос успешным или нет.

Вы можете определить режим для запроса на выборку, чтобы разрешались только определенные запросы. Вы можете установить следующие режимы:

  • same-origin успешен только для запросов на активы из того же источника, все остальные запросы будут отклонены.
  • cors разрешит запросы к ресурсам того же и других источников, которые возвращают соответствующие заголовки COR.
  • cors-with-forced-preflight всегда выполняет предполетную проверку перед фактическим запросом.
  • no-cors предназначен для отправки запросов к другим источникам, которые не имеют заголовков CORS и приводят к opaque ответу, но, как уже говорилось, на данный момент это невозможно в глобальной области видимости окна.

Чтобы определить режим, добавьте объект параметров в качестве второго параметра в запросе fetch и определите режим в этом объекте:

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

Объединение обещаний

Одной из замечательных особенностей промисов является возможность связывать их вместе. Для выборки это позволяет вам использовать логику для разных запросов на выборку.

Если вы работаете с API JSON, вам нужно будет проверять статус и анализировать JSON для каждого ответа. Вы можете упростить свой код, определив статус и анализ JSON в отдельных функциях, которые возвращают обещания, что позволит вам беспокоиться только об обработке окончательных данных и случае ошибки.

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

Мы определяем функцию status , которая проверяет ответ.статус и возвращает результат Promise.resolve() или Promise.reject() , которые возвращают решенный или отклоненный обещание. Это первый метод, вызываемый в нашей цепочке fetch() . Если он разрешается, мы затем вызываем наш метод json() , который снова возвращает обещание из вызова response.json() . После этого у нас есть объект разобранного JSON. Если синтаксический анализ завершается неудачно, обещание отклоняется и выполняется оператор catch.

Самое замечательное в этом то, что вы можете использовать логику для всех ваших запросов на выборку, что упрощает поддержку, чтение и тестирование кода.

POST-запрос

Веб-приложения нередко требуют вызвать API с помощью метода POST и предоставить некоторые параметры в теле запроса.

Для этого мы можем установить параметры method и body в опциях fetch() .

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

Отправка учетных данных с помощью запроса на выборку

Если вы хотите сделать запрос на выборку с учетными данными, такими как файлы cookie, вам следует установить для credentials запроса значение "include" .

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

Часто задаваемые вопросы

Как отменить запрос fetch()?

На данный момент возможности отменить выборку нет, но это обсуждается на GitHub . Привет @jaffathecake за эту ссылку.

Есть ли полифил?

В GitHub есть полифилл для fetch . H/T @Nexii за указание на это.

Почему «no-cors» поддерживается в сервис-воркерах, но не в окне?

Это связано с соображениями безопасности, подробнее можно узнать здесь .