Может быть, вы не так много знаете о Fetch (Часть 1)

внешний интерфейс HTTP
Может быть, вы не так много знаете о Fetch (Часть 1)

Примечание редактора: Помимо интерфейса Chuangyu и блога автора, эта статья также опубликована в Yuque.

Примечание редактора: Автор также находится в Наггетс, прошу обратить внимание:@GoDotDotDot

предисловие

В этой статье в основном говорится оFetchНекоторые базовые знания и то, как мы их используем в производственной разработке. Чтобы лучше понятьFetch, мы надеемся, что у вас есть некоторое понимание следующих моментов знаний.Если у вас есть соответствующий опыт разработки, это лучше всего.

Некоторые ключевые слова оснащены соответствующими ссылками в этой статье. Если вы не знаете достаточно о ключевых слов или хотите узнать больше, вы можете обогатить себя, нажав на него. Некоторые точки знаний в текстеMDN FetchОна написана очень подробно, поэтому я ее пропущу, надеюсь, что студенты смогут читать ее параллельно при чтении этой статьи.

Идея этой статьи исходит изТехнические характеристикиДля начала, цель состоит в том, чтобы дать всем понять более тщательно, чтобы знать, что это такое и почему это.

для лучшего контроляFetch, в статье также приведены некоторыеобразец кодаДля всех, чтобы изучить и использовать. Прежде чем использовать этот пример кода, мы надеемся, что выnode.js Имейте некоторое понимание, если нет, вы можете завершить свое обучение, следуя дружеским советам в примере.

Прочитав эту статью, вы будете знать следующее:

  • чтоFetch
  • Fetchнекоторые основные понятия о
  • как использоватьFetch
  • FetchНекоторые недостатки и как мы «элегантно» это используем

Надеюсь, после прочтения этой статьи вы получили базовое представление о Fetch.

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

Fetchэто новая технология получения ресурсов, она используется для замены технологии, на которую мы давно жалуемся (XHR).

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

fetch('https://github.com/frontend9/fe9-library', {
method: 'get'
}).then(function(response) {
}).catch(function(err) {
// Error
});

Нельзя ли проще? Ну, так как мыFetchПосле того, как у нас есть простое понимание, давайте разберемсяFetchосновная концепция.

Получить основные понятия

существуетFetchЕсть четыре основных понятия, ониHeaders,Request,Responseа такжеBody. для лучшего пониманияFetch, нам нужно краткое понимание этих понятий.

в полномHTTPПо запросу эти четыре концепции уже включены. Запросы имеют запрос в заголовки и запрос органам, а ответы имеют ответы заголовки и ответные органы. Так что нам нужно понять эти концепции.

Headers

Для достижения гибкости головы головка может быть изменена, является очень важным возможностями. Заголовки принадлежатHTTPсерединастолицаЧасть , это абстрактный интерфейс, который можно использовать дляHTTPдобавлять, изменять и удалять заголовки запросов и ответов.

Давайте посмотрим, какие у него есть интерфейсы:

typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;

[Constructor(optional HeadersInit init),
 Exposed=(Window,Worker)]
interface Headers {
  void append(ByteString name, ByteString value);
  void delete(ByteString name);
  ByteString? get(ByteString name);
  boolean has(ByteString name);
  void set(ByteString name, ByteString value);
  iterable<ByteString, ByteString>;
};interface Headers {
  void append(ByteString name, ByteString value);
  void delete(ByteString name);
  ByteString? get(ByteString name);
  boolean has(ByteString name);
  void set(ByteString name, ByteString value);
  iterable<ByteString, ByteString>;
};
// 来自 https://fetch.spec.whatwg.org/#headers-class

Интерфейс, определенный в спецификации, может соответствоватьMDNдля просмотра вы можете нажатьздесьДавайте более интуитивно посмотрим, какие методы он может нам использовать.

Здесь у нас естьHeadersобъяснить параметры конструкции. Первый тип параметраHeadersInit, давайте посмотрим, какие типы значений поддерживает этот тип. Определения, которые мы можем видеть из спецификации:

typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;

Здесь мы соответствуемJavaScriptЭтот язык означает, что объект может быть массивом или парой ключа (то есть объекты). О том, как инициализировать эти параметры, мы можем выглядеть определенным в спецификацииобработать.

To fill a Headers object (headers) with a given object (object), run these steps:

  1. If object is a sequence, then for each header in object:
    1. If header does not contain exactly two items, then throw a TypeError.
    2. Appendпервый элемент заголовка/второй элемент заголовка в headers.
  2. Otherwise, object is a record, then for eachключ → значение в объекте,append key/value to headers.

Здесь мне нужно объяснить это, и использование выборки будет включать в себя немного и то, что мы видимpolyfillпоможет.

  • Первый: массив, когда каждый элемент данных не содержит двух элементов, сразу будет выброшена ошибка. Тогда первый элемент массиваheaderимя, а второй элемент — значение. , и, наконец, непосредственно черезappendдобавлен метод.
  • Второй: пара ключ-значение (здесь имеется в виду объект), мы напрямую получаем пару ключ-значение через цикл, а затем передаемappendдобавлен метод.

Пример

Пример кода адреса:GitHub.com/годо точка точка…

Откройте браузер и введите:http://127.0.0.1:4000/headers

Итак, как мы его используем? Сначала нам нужно пройтиnew Headers()для создания экземпляра объекта Headers, который возвращает пустой список. После того, как у нас есть экземпляр объекта, мы можем делать с интерфейсом то, что хотим.Давайте рассмотрим следующий пример:

  function printHeaders(headers) {
    let str = '';
    for (let header of headers.entries()) {
      str += `
          <li>${header[0]}: ${header[1]}</li>
          `;
      console.log(header[0] + ': ' + header[1]);
    }
    return `<ul>
          ${str}
          </ul>`;
  }
  const headers = new Headers();
  // 我们打印下看看是否返回的是一个空的列表
  const before = printHeaders(headers); // 发现这里没有任何输出
  document.getElementById('headers-before').innerHTML = before;
  // 我们添加一个请求头
  headers.append('Content-Type', 'text/plain');
  headers.append('Content-Type', 'text/html');
  headers.set('Content-Type', ['a', 'b']);
  const headers2 = new Headers({
    'Content-Type': 'text/plain',
    'X-Token': 'abcdefg',
  });
  const after = printHeaders(headers); // 输出:content-type: 

Если вы чувствуете, что каждый разappendВ случае проблем вы также можете передать указанный заголовок в конструкторе, например:

const headers2 = new Headers({
    'Content-Type': 'text/plain',
'X-Token': 'abcdefg'
});

printHeaders(headers2);
// 输出:
// content-type: text/plain
// x-token: abcdefg

Здесь я добавляю пользовательский заголовокX-Token, что очень распространено и практично в практической разработке. Но помниCORSДолжны быть соблюдены соответствующие спецификации, иначе возникнет междоменная ошибка.

ты можешь пройтиappend,delete,set,getа такжеhasметод для изменения заголовков запроса. Прямо здесьsetа такжеappendСпециальное описание метода:

set: если вы работаете с существующим заголовком, новое значение заменит старое значение, а старое значение не будет существовать. Если заголовок не существует, добавьте новый заголовок напрямую.

append: если заголовок уже существует, новое значение добавляется непосредственно к концу, а старое значение также сохраняется.

Для легкой памяти нужно просто запомнитьsetпокроет, покаappendбудет добавлено.

Guard

Охранник - это особенность заголовков, он опекун. Это влияет на некоторые методы (какappend,set,delete) можно изменить заголовок заголовка.

Он может иметь следующие значения:immutable,request,request-no-cors,responseилиnone.

Вам не нужно беспокоиться об этом здесь, просто чтобы вы знали, что есть такая вещь, влияющая на нас, чтобы установить некоторые заголовки. Вы также не можете манипулировать им, это прокси-вещь. В качестве простого примера, мы не можем вставить заголовки ответаSet-Cookie.

Если вы хотите узнать более подробную информацию, пожалуйста, обратитесь к конкретной спецификацииconcept-headers-guardа такжеMDN Guard

Уведомление

Body

Тело, если быть точным, здесь простоmixin, представляющий тело запроса или тело ответа, указанноеResponseа такжеRequestреализовать.

Давайте посмотрим, какие у него есть интерфейсы:

interface mixin Body {
  readonly attribute ReadableStream? body;
  readonly attribute boolean bodyUsed;
  [NewObject] Promise<ArrayBuffer> arrayBuffer();
  [NewObject] Promise<Blob> blob();
  [NewObject] Promise<FormData> formData();
  [NewObject] Promise<any> json();
  [NewObject] Promise<USVString> text();
};
// 来自 https://fetch.spec.whatwg.org/#body

Интерфейс, определенный в спецификации, может соответствоватьMDNдля просмотра вы можете нажатьздесьБолее интуитивно понятно, какие свойства и методы мы можем использовать.

Здесь следует отметить, что эти методы возвращаютPromise, помните, что это основано наfetchЭто очень важно при выполнении интерфейсных запросов. Помните об этом, это поможет нам понять в следующих статьяхfetchПрименение.

Пример

Примеры будут вResponseотражено в.

Request

Запрос представляет класс запроса, который необходимо создать для создания объекта запроса. Через этот объект можно описатьHTTPЗапрос в запросе (обычно содержит заголовки запроса и тело запроса). Поскольку он используется для описания объекта запроса, объект запроса должен иметь способ изменить заголовок запроса (Заголовки) и тело запроса (Тело). Давайте сначала посмотрим, какие интерфейсы есть у Request в спецификации:

typedef (Request or USVString) RequestInfo;

[Constructor(RequestInfo input, optional RequestInit init),
 Exposed=(Window,Worker)]
interface Request {
  readonly attribute ByteString method;
  readonly attribute USVString url;
  [SameObject] readonly attribute Headers headers;

  readonly attribute RequestDestination destination;
  readonly attribute USVString referrer;
  readonly attribute ReferrerPolicy referrerPolicy;
  readonly attribute RequestMode mode;
  readonly attribute RequestCredentials credentials;
  readonly attribute RequestCache cache;
  readonly attribute RequestRedirect redirect;
  readonly attribute DOMString integrity;
  readonly attribute boolean keepalive;
  readonly attribute boolean isReloadNavigation;
  readonly attribute boolean isHistoryNavigation;
  readonly attribute AbortSignal signal;

  [NewObject] Request clone();
};
Request includes Body;

dictionary RequestInit {
  ByteString method;
  HeadersInit headers;
  BodyInit? body;
  USVString referrer;
  ReferrerPolicy referrerPolicy;
  RequestMode mode;
  RequestCredentials credentials;
  RequestCache cache;
  RequestRedirect redirect;
  DOMString integrity;
  boolean keepalive;
  AbortSignal? signal;
  any window; // can only be set to null
};

enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "image", "manifest", "object", "paintworklet", "report", "script", "sharedworker", "style",  "track", "video", "worker", "xslt" };
enum RequestMode { "navigate", "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
// 来自 https://fetch.spec.whatwg.org/#request-class

Интерфейс, определенный в спецификации, может соответствоватьMDNдля просмотра вы можете нажатьздесьДавайте более интуитивно посмотрим, какие свойства и методы он может нам использовать, и мы не будем объяснять их здесь по одному.

Обратите внимание, что все свойства здесь доступны только для чтения, в спецификации мы видим, что первый параметр конструктораRequestОбъект или строка, мы вообще берем строку, то есть адрес ресурса, к которому нужно получить доступ (HTTPадрес интерфейса). Второй параметр получаетRequestInitНеобязательный объект, и этот объект является словарем. существуетjavascript, мы можем понимать это как объект ({}).RequestInitВнутри мы можем настроить начальные свойства, сообщаяRequestНекоторая информация о конфигурации для нашего запроса.

Здесь необходимо обратить особое внимание на следующие свойства.

modeЯвляетсяRequestModeТип перечисления, возможные значенияnavigate, same-origin, no-cors, cors. Указывает, используется ли запросCORSили используйте режим строгой гомологии. В междоменной ситуации вы должны установитьcors. Значение по умолчанию для этого значения используетRequestПри инициализации по умолчаниюcors. Когда встроенные ресурсы запускаются с тегами, такими как<link>,<script>Ярлыки (не измененные вручнуюcrossoriginсвойство), по умолчаниюno-cors. Для получения подробной информации см.whatwgнорма илиMDN.

credentialsЯвляетсяRequestCredentialsТип перечисления, возможные значенияomit, same-origin, include. Указывает, отправляется ли запрос в междоменной ситуации.cookie. посмотри это если правильноXHRСтуденты, которые знают его, должны быть знакомы с ним. с участиемXHRсерединаwithCredentialsочень похожий. ноcredentialsЕсть три необязательных значения, его значение по умолчанию равноsame-origin. Когда вам нужно пройти через доменыcookieучетные данные, установите его наinclude. Обратите внимание, что здесь есть детали, когда установлено значениеinclude, Пожалуйста, убедитесьResponse HeaderсерединаAccess-Control-Allow-Originне может быть*, необходимо указать источник (например:http://127.0.0.1:4001), иначе вы увидите следующее сообщение об ошибке в консоли. Для получения подробной информации см.whatwgнорма илиMDN.

The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

Вы можете использовать код, приведенный в статье, чтобы начать cors образец кодаЗатем введите браузер http://127.0.0.1:4001/request, если ничего другого, вы можете увидеть вышеуказанное сообщение об ошибке в консоли.

bodyЯвляетсяBodyInitТипы. Его возможные значенияBlob,BufferSource , FormData , URLSearchParams , ReadableStream , USVString. Внимательные ученики не знают, нашли ли они его, мы частоjsonОбъекта нет. Поэтому, если нам нужно пройтиjsonЕсли вам нужно позвонитьJSON.stringifyфункция, которая поможет нам преобразовать в строку.

Пример кода приведен ниже.

Пример

Пример кода адреса:GitHub.com/годо точка точка…

Откройте браузер и введите:http://127.0.0.1:4000/request

  // 客户端
  const headers = new Headers({
    'X-Token': 'fe9',
  });
  const request = new Request('/api/request', {
    method: 'GET',
    headers,
  });
  console.log(request); // Request {method: "GET", url: "http://127.0.0.1:4000/api/request", headers: Headers, destination: "", referrer: "about:client", …}
  console.log(request.method); // GET
  console.log(request.mode); // cors
  console.log(request.credentials); // same-origin
  // 如果你想打印headers信息,可以调用 printHeaders(request.headers)

Здесь мы первыеGETПростой запрос в качестве примера, мы передаем пользовательскийHeaders, указав метод запросаmethodдляGET(по умолчаниюGET). В приведенной выше спецификации интерфейса мы можем передатьRequestОбъект получает некоторые часто используемые свойства, такие какmethod,url,headers,bodyи так далее свойства только для чтения.

Response

Response аналогичен Request и представляет данные ответа, возвращаемые запросом. Давайте сначала посмотрим, какие интерфейсы определены в спецификации.

[Constructor(optional BodyInit? body = null, optional ResponseInit init), Exposed=(Window,Worker)]
interface Response {
  [NewObject] static Response error();
  [NewObject] static Response redirect(USVString url, optional unsigned short status = 302);

  readonly attribute ResponseType type;

  readonly attribute USVString url;
  readonly attribute boolean redirected;
  readonly attribute unsigned short status;
  readonly attribute boolean ok;
  readonly attribute ByteString statusText;
  [SameObject] readonly attribute Headers headers;
  readonly attribute Promise<Headers> trailer;

  [NewObject] Response clone();
};
Response includes Body;

dictionary ResponseInit {
  unsigned short status = 200;
  ByteString statusText = "";
  HeadersInit headers;
};

enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
// 来自 https://fetch.spec.whatwg.org/#response-class

Интерфейс, определенный в спецификации, может соответствоватьMDNдля просмотра вы можете нажатьздесьДавайте более интуитивно посмотрим, какие свойства и методы он может нам использовать, и мы не будем объяснять их здесь по одному.

вstatus, headersСвойства используются чаще всего. пройти черезstatusКод состояния мы можем судить о результате обработки запроса сервера, например200, 403и т.д. Общие коды состояния. Вот пример, когдаstatusдля401, вы можете перехватить и перейти на страницу входа в систему во внешнем интерфейсе, которая сейчасSPA(Одностраничные приложения). мы также можем использоватьheadersЧтобы получить некоторую информацию, возвращаемую сервером во внешний интерфейс, напримерtoken.

Студенты, которые внимательно изучают приведенный выше интерфейс, могут обнаружить, чтоResponse includes Body;такая идентификация. Раньше мы говорилиBodyЗависит отRequestа такжеResponseвыполнить. такBodyесть метод вResponseМожно использовать экземпляры, и это тоже очень важная часть, проходимBodyПредоставленный метод (здесь точно определяетсяResponseРеализовано) для обработки данных, возвращаемых сервером.

Ниже мы будем использовать пример, чтобы понять простое использование:

Пример

Расположение примера кода:GitHub.com/годо точка точка…

  // 客户端
  const headers = new Headers({
    'X-Token': 'fe9-token-from-frontend',
  });
  const request = new Request('/api/response', {
    method: 'GET',
    headers,
  });

  // 这里我们先发起一个请求试一试
  fetch(request)
    .then(response => {
      const { status, headers } = response;
      document.getElementById('status').innerHTML = `${status}`;
      document.getElementById('headers').innerHTML = headersToString(headers);

      return response.json();
    })
    .then(resData => {
      const { status, data } = resData;
      if (!status) {
        window.alert('发生了一个错误!');
        return;
      }
      document.getElementById('fetch').innerHTML = data;
    });

Здесь мы игнорируемfetchиспользования, которые будут подробно описаны в следующих главах. Сосредоточимся на первомthenМетод вызывает то, что внутри. Видно, что возвратresponseобъект, этот объект нашResponseпример. взято в примерstatusа такжеheaders, для удобства здесь выложил в html. Глядя на последнюю строку обратного вызова, мы вызываемresponse.json()метод (данные, возвращаемые здесь, являютсяJSONобъекта, для удобства прямого вызоваjson()), метод возвращаетPromise, возвращаем результат обработки последнемуthenОбратный вызов, чтобы можно было получить окончательные обработанные данные.

Откройте браузер и введитеhttp://127.0.0.1:4000/response, если код вашего примера работает правильно, вы увидите следующую страницу:

img

(см. данные, возвращаемые Response)

Примечание редактора: эта статья незакончена.


Искусство /GoDotDotDot

Less is More.

редактировать /флуоресценция

Другие статьи автора:

Отличные темы, которые необходимо знать: мы должны сделать все возможное для оптимизации

Эта статья авторизована и опубликована автором Chuangyu Front-end, а авторские права принадлежат автору, созданному Chuangyu Front-end. Пожалуйста, укажите источник для перепечатки этой статьи. Ссылка на статью:blog.Godot точка точка.com/2018/12/28/…

Если вы хотите подписаться на другие сообщения с передовой линии KnownsecFED, выполните поиск и подпишитесь на нашу общедоступную учетную запись WeChat: KnownsecFED. Добро пожаловать, чтобы оставить сообщение для обсуждения, мы ответим как можно скорее.

Спасибо за прочтение.

С новым годом :)