[JS Pocket Book] Глава 10: Использование асинхронного JavaScript

JavaScript ECMAScript 6

Добавить Автора

Переводчик: Front-end Xiaozhi

Источник: гитхаб


Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.

REST API и XMLHttpRequest

Если вы спросите меня, я бы сказал, что JS довольно мощен. Как язык сценариев, который работает в браузере, он может делать все, например:

  • Динамическое создание элементов
  • добавить интерактивность

и т.п. в8В главе 1 мы начали с массива и построилиHTMLлист. Захардкоженный массив — это синхронный источник данных, то есть его можно использовать прямо в нашем коде без ожидания. Но в большинстве случаев данные запрашиваются из фона. Сетевые запросы — это всегда асинхронные операции, а не синхронные источники данных: запрашиваются данные, а сервер отвечает с некоторой задержкой.

Сам JS не имеет встроенной асинхронности: это среда «хостинга» (браузер или Node.j), которая предоставляет внешнюю помощь для обработки трудоемких операций. существуетГлава 3, мы видимsetTimeoutа такжеsetInterval, эти два принадлежатWeb APIиз. Браузер предоставляет множество API, один из которых называетсяXMLHttpRequestОн специально используется для сетевых запросов.

На самом деле, это происходит отXMLЭпоха форматов данных. СейчасJSONявляется наиболее популярным коммуникационным «протоколом» для перемещения данных между веб-сервисами, ноXMLHttpRequestВ конечном итоге название было сохранено.

XMLHttpRequestСлишкомAJAXчасть технологии, это«Асинхронный JavaScript и XML»аббревиатура от.AJAXОн был создан для максимально гибкой обработки сетевых запросов в браузере. Что он делает, так это может извлекать данные из удаленного источника данных, не вызывая обновления страницы. Идея была почти революционной в то время. вместе сXMLHttpRequestПредставленный (около 13 лет назад), мы можем использовать его для выполнения асинхронных запросов.

var request = new XMLHttpRequest();

request.open('GET', "https://academy.valentinog.com/api/link/");

request.addEventListener('load', function() {
  console.log(this.response);
})

request.send();

В приведенном выше примере:

  • создать новыйXMLHttpRequestобъект

  • Откройте запрос, указав метод и URL

  • Зарегистрируйте прослушиватель событий

  • послать запрос

XMLHttpRequestосновывается наDOM-событияДа, мы можем использоватьaddEventListenerилиonloadследить"load"событие, которое срабатывает при успешном выполнении запроса. Для неудачных запросов (сетевых ошибок) мы можем сделать это в "error” для регистрации слушателя:

var request = new XMLHttpRequest();

request.open("GET", "https://academy.valentinog.com/api/link/")

request.onload = function() {
  console.log(this.response)
}

request.onerror = function() {
  // 处理错误
}

request.send();

Обладая этими знаниями, мы можем лучше использоватьXMLHttpRequest.

Запрос данных через XMLHttpRequest, создание списка HTML

отREST APIПосле извлечения данных мы построим простой HTML-список. Недавно построенное имяbuild-list.htmlдокумент:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>XMLHttpRequest</title>
</head>
<body>

</body>
<script src="xhr.js"></script>
</html>

Далее в этой же папке создайте файл с именемxhr.jsдокумент. В этом файле создайте новыйXHRпросить:

"use strict";

const request = new XMLHttpRequest();

Приведенный выше вызов (способ конструктора) создаетXMLHttpRequestНовый объект типа. а такжеsetTimeoutи т. д. Вместо асинхронных функций мы ставимПерезвонитеВ качестве параметра:

setTimeout(callback, 10000);

function callback() {
  console.log("hello timer!");
}

XMLHttpRequestОсновываясь на событиях DOM, обратные вызовы обработчиков регистрируются вonloadна объекте. Когда запрос будет успешным,loadСобытие запущено.

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  console.log("Got the response!");
}

После регистрации обратного вызова мы можем использоватьopen()Открытый запрос. он принимаетHTTPметод

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  console.log("Got the response!");
}

request.open("GET", "https://academy.valentinog.com/api/link/");

Наконец, мы можем использоватьsend()отправить актуальный запрос

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  console.log("Got the response!");
}

request.open("GET", "https://academy.valentinog.com/api/link/");
request.send();

открыть в браузереbuild-list.html, вы увидите в консоли“Got the response!”, что означает, что запрос выполнен успешно. если ты помнишьГлава 6, каждая обычная функция JS имеет ссылку на свой хост-объект. потому что обратный вызов находится вXMLHttpRequestобъект, так что вы можете пройтиthis.responseПолучить данные, возвращенные сервером.

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  // this refers to the new XMLHttpRequest
  // response is the server's response
  console.log(this.response);
}

request.open("GET", "https://academy.valentinog.com/api/link/");
request.send();

сохраните файл и обновитеbuild-list.html. Вы можете увидеть возвращенные данные в консоли. Формат данных — строка. Есть два способа преобразовать их в формат JSON:

  • Способ 1:XMLHttpRequestРасполагается на объекте в соответствии с типом

  • Способ 2: ИспользованиеJSON.parse()

метод первый:

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  // this refers to the new XMLHttpRequest
  // response is the server's response
  console.log(this.response);
}

// configure the response type
request.responseType = "json";
//

request.open("GET", "https://academy.valentinog.com/api/link/");
request.send();

Рекомендуется метод 2, а также в соответствии с нашими текущими привычками программирования:

"use strict";

const request = new XMLHttpRequest();

request.onload = callback;

function callback() {
  const response = JSON.parse(this.response);
  console.log(response);
}

request.open("GET", "https://academy.valentinog.com/api/link/");
request.send();

обновить сноваbuild-list.html, вы увидите массив объектов JS, каждый из которых имеет одинаковую структуру:

[
  //
  {
    title:
      "JavaScript Engines: From Call Stack to Promise, (almost) Everything You Need to Know",
    url: "https://www.valentinog.com/blog/engines/",
    tags: ["javascript", "v8"],
    id: 3
  }
  //
]

В этот раз мы неГлава 8Таким же образом создайте массив вручную, но запросите данные через интерфейс REST API.

Создание списков HTML (и классов отладки) с помощью JS

Здесь мы используем методы класса ES6 для сборки, а также делаемИспользуйте поля закрытого класса(На момент написанияFirefoxЭто поле не поддерживается). Прежде чем писать какой-либо код, подумайте, как кто-то другой будет «использовать мой класс»? Например, другой разработчик может использовать наш код и вызвать класс, передав:

  • URL для получения данных

  • Элемент HTML для добавления списка к

    const url = "academy.valentinog.com/api/link/"; const target = document.body; const list = new List(url, target);

С учетом этих требований мы можем приступить к написанию кода класса. В настоящее время он должен принимать два параметра в конструкторе и иметь метод получения данных.

class List {
  constructor(url, target) {
    this.url = url;
    this.target = target;
  }

  getData() {
    return "stuff";
  }
}

В разработке программного обеспечения распространено мнение, что доступ к членам и методам класса извне невозможен, если нет веских причин сделать обратное. В JS, если вы не используете модули, нет собственного способа скрыть методы и переменные (глава 2). даже еслиclassОн не застрахован от утечки информации, но с приватными полями таких проблем можно избежать с большой вероятностью. Поле закрытого класса JS еще не стало стандартом, но большинство браузеров уже поддерживают его.#Чтобы представить, перепишите приведенный выше класс:

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
  }

  getData() {
    return "stuff";
  }
}

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

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
  }

  getData() {
    return "stuff";
  }
}

const url = "https://academy.valentinog.com/api/link/";
const target = document.body;
const list = new List(url, target);

console.log(list.url); // undefined
console.log(list.target); // undefined

С помощью этой структуры мы можем переместить логику выборки данных вgetDataсередина.

"use strict";

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
  }

  getData() {
    const request = new XMLHttpRequest();
    request.onload = function() {
      const response = JSON.parse(this.response);
      console.log(response);
    };

    request.open("GET", this.#url);
    request.send();
  }
}

const url = "https://academy.valentinog.com/api/link/";
const target = document.body;
const list = new List(url, target);

Теперь, чтобы отобразить данные, мы находимся вgetDataПосле этого добавьте файл с именемrenderМетоды.renderСоздаст для нас HTML-список, начиная с массива параметров:

"use strict";

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
  }

  getData() {
    const request = new XMLHttpRequest();
    request.onload = function() {
      const response = JSON.parse(this.response);
      console.log(response);
    };

    request.open("GET", this.#url);
    request.send();
  }

  // The new method
  render(data) {
    const ul = document.createElement("ul");
    for (const element of data) {
      const li = document.createElement("li");
      const title = document.createTextNode(element.title);
      li.appendChild(title);
      ul.appendChild(li);
    }
    this.#target.appendChild(ul);
  }
}

Уведомлениеdocument.createElement(),document.createTextNode()а такжеappendChild(). мыГлава 8Я видел это, когда говорил о манипулировании DOM.this.#targetЗакрытое поле добавляет HTML-список к DOM. Теперь я хочу:

  • Вызывается после получения ответа JSONrender

  • Немедленно вызывается, когда пользователь создает новый список "экземпляр"getData

Для этого мыrequest.onloadОбратный вызов внутренний вызовrender:

getData() {
  const request = new XMLHttpRequest();
  request.onload = function() {
    const response = JSON.parse(this.response);
    // Call render after getting the response
    this.render(response);
  };

  request.open("GET", this.#url);
  request.send();
}

с другой стороны,getDataдолжен работать в конструкторе:

constructor(url, target) {
  this.#url = url;
  this.#target = target;
  // Call getData as soon as the class is used
  this.getData();
}

Полный код:

"use strict";

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
    this.getData();
  }

  getData() {
    const request = new XMLHttpRequest();
    request.onload = function() {
      const response = JSON.parse(this.response);
      this.render(response);
    };

    request.open("GET", this.#url);
    request.send();
  }

  render(data) {
    const ul = document.createElement("ul");
    for (const element of data) {
      const li = document.createElement("li");
      const title = document.createTextNode(element.title);
      li.appendChild(title);
      ul.appendChild(li);
    }
    this.#target.appendChild(ul);
  }
}

const url = "https://academy.valentinog.com/api/link/";
const target = document.body;
const list = new List(url, target);

Попробуйте: обновить в браузереbuild-list.htmlи посмотри на консоль

Uncaught TypeError: this.render is not a function

this.renderНе функция! Что бы это могло быть? На этом этапе вы можете захотеть достичьГлава 6или позже код можно отлаживать. существуетgetData серединаthis.render(response)После этого добавьтеdebuggerинструкция:

getData() {
  const request = new XMLHttpRequest();
  request.onload = function() {
    const response = JSON.parse(this.response);
    debugger;
    this.render(response);
};

request.open("GET", this.#url);
  request.send();
}

debuggerДобавляется так называемая точка останова, и выполнение останавливается там. Теперь откройте консоль браузера и обновитеbuild-list.html. Вот что вы увидите в Chrome:

Пристальный взгляд"Scopes"Таб.getDataдействительно есть одинthis, но указывает наXMLHttpRequest. Другими словами, мы пытаемся получить доступ не к тому объекту.this.render.

ЗачемthisНесоответствие? Это связано с тем, что переход кrequest.onloadОбратный вызов выполняется в хост-объекте типа XMLHttpRequest, вызываяconst request = request = new XMLHttpRequest()результат. Обходной путь, упомянутый в предыдущих главах, можно выполнить с помощью箭头函数.

  getData() {
    const request = new XMLHttpRequest();
    // The arrow function in action
    request.onload = () => {
      const response = JSON.parse(this.response);
      debugger;
      this.render(response);
    };

    request.open("GET", this.#url);
    request.send();
  }

обновитьbuild-list.htmlи проверь это

Uncaught SyntaxError: Unexpected token u in JSON at position 0

Отлично, предыдущая ошибка исчезла, но теперьJSON.parseВозникла проблема. Мы можем легко представить это с помощьюthisСвязанный. Будуdebuggerперейти на одну строку вверх

  getData() {
    const request = new XMLHttpRequest();
    request.onload = () => {
      debugger;
      const response = JSON.parse(this.response);
      this.render(response);
    };

    request.open("GET", this.#url);
    request.send();
  }
    

обновитьbuild-list.htmlи еще раз посмотри в консоли браузераScopes.responseдаundefined, потому что мы хотим получить доступthisдаList. Это согласуется с поведением стрелочных функций и классов (классы по умолчанию работают в строгом режиме). Так есть ли решение сейчас?

отГлава 8Как известно из DOM и событий, каждый обратный вызов, переданный в качестве прослушивателя событий, имеет доступ кeventобъект. вeventСуществует такжеtargetсвойство, указывающее на объект, вызвавший событие. Вы можете пройтиevent.target.responseПолучите данные, возвращенные ответом.

 getData() {
    const request = new XMLHttpRequest();
    request.onload = event => {
      const response = JSON.parse(event.target.response);
      this.render(response);
    };

    request.open("GET", this.#url);
    request.send();
  }

Полный код:

"use strict";

class List {
  #url;
  #target;

  constructor(url, target) {
    this.#url = url;
    this.#target = target;
    this.getData();
  }

  getData() {
    const request = new XMLHttpRequest();
    request.onload = event => {
      const response = JSON.parse(event.target.response);
      this.render(response);
    };

    request.open("GET", this.#url);
    request.send();
  }

  render(data) {
    const ul = document.createElement("ul");
    for (const element of data) {
      const li = document.createElement("li");
      const title = document.createTextNode(element.title);
      li.appendChild(title);
      ul.appendChild(li);
    }
    this.#target.appendChild(ul);
  }
}

const url = "https://academy.valentinog.com/api/link/";
const target = document.body;
const list = new List(url, target);    

Далее продолжайте исследоватьXMLHttpRequestразвитие:Fetch.

Асинхронная эволюция: от XMLHttpRequest к выборке

Fetch APIэто способ выпускаAJAXСобственный браузерный метод запроса, который часто используется, напримерAxiosТакие библиотеки игнорируются. Fetch с ES6 и новымиPromiseОбъекты родились вместе в 2015 году.

С другой стороны, с 1999 года AJAX использует набор методов для получения данных в браузере. Теперь мы воспринимаем AJAX и Fetch как должное, но мало кто знаетFetchэто толькоXMLHttpRequestиз "美化版".Fetchчем обычноXMLHttpRequestЗапрос более краток и, что более важно, основан наPromise. Вот простой случай:

fetch("https://academy.valentinog.com/api/link/").then(function(response) {
  console.log(response);
});

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

fetch("https://academy.valentinog.com/api/link/").then(function(response) {
  return response.json();
}); 

Вопреки тому, что вы могли бы подумать, простой вызов не возвращает фактических данных. из-заresponse.json()также возвращаетPromise, поэтому для получения полезной нагрузки JSON требуется еще один шаг:

fetch("https://academy.valentinog.com/api/link/")
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  });

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

Перестройте Fetch API с нуля

Чтобы лучше понять принцип работы Fetch, перепишемfetchметод. Сначала создайте файл с именемfetch.htmlновый файл со следующим содержимым:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Building Fetch from scratch</title>
</head>
<body>

</body>
<script src="fetch.js"></script>
</html>

Затем в той же папке создайте еще один файл с именемfetch.jsфайл со следующим содержимым:

"use strict";

window.fetch = null;

В первой строке убеждаемся в строгом режиме, а во второй строке «отменяем» исходныйFetch API. Теперь мы можем приступить к созданию собственногоFetch API.fetchПринцип работы очень прост. он принимаетurlи выпуститьGETпросить:

fetch("https://academy.valentinog.com/api/link/").then(function(response) {
  console.log(response);
});

когда сthenФункция, в которой говорится, что функция является "цепной", что означает, что она возвращаетPromise. Таким образом, вfetch.js, мы создаемfetchфункция, которая принимаетurlи вернуть новыйPromise. СоздайтеPromise, который можно назватьPromiseконструктор и передать функцию обратного вызова для анализа и отклонения:

function fetch(url) {
  return new Promise(function(resolve, reject) {
    // do stuff
  });
}

Заполните код:

"use strict";

window.fetch = fetch;

function fetch(url) {
  return new Promise(function(resolve, reject) {
    resolve("Fake response!");
  });
}

fetch("https://academy.valentinog.com/api/link/").then(function(response) {
  console.log(response);
});

Получил "Фальшивый ответ!" в консоли. Конечно, это все равно бесполезноfetch, так как API ничего не возвращает. разрешите намXMLHttpRequestс помощью реального поведения. мы уже знаемXMLHttpRequestСоздайте метод запроса. Далее будетXMLHttpRequestупаковано в нашуPromiseсередина

function fetch(url) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    request.open("GET", url);
    request.onload = function() {
      resolve(this.response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    request.send();
  });
}

ОтклоненныйPromiseЗависит отcatchиметь дело с:

fetch("https://acdemy.valentinog.com/api/link/")
  .then(function(response) {
    console.log(response);
  })
  .catch(function(error) {
    console.log(error);
  });

Сейчас еслиurlневерно, выведет на консоль конкретное сообщение об ошибке. еслиurlИсправьте, затем распечатайте запрос к данным:

Описанный выше способ реализации не идеален. Во-первых, нам нужно реализовать возвратJSONФункция. действительныйFetch APIСгенерируйте ответ, который впоследствии можно преобразовать в JSON, большой двоичный объект или текст, как показано ниже (в рамках этого упражнения мы будем реализовывать только функции JSON).

fetch("https://academy.valentinog.com/api/link/")
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  })

Реализация этой функции должна быть простой. похоже на то "response” может быть синглом сjson()Сущность функции. Система прототипов JS отлично подходит для создания кода (см. главу 5). Мы создаем конструктор с именем Response и метод, привязанный к его прототипу (вfetch.jsсередина):

function Response(response) {
  this.response = response;
}

Response.prototype.json = function() {
  return JSON.parse(this.response);
};

Вот и все, мы можем использовать Response в Fetch:

window.fetch = fetch;

function Response(response) {
  this.response = response;
}

Response.prototype.json = function() {
  return JSON.parse(this.response);
};

function fetch(url) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    request.open("GET", url);
    request.onload = function() {
      // 前面:
      // resolve(this.response);
      // 现在:
      const response = new Response(this.response);
      resolve(response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    request.send();
  });
}

fetch("https://academy.valentinog.com/api/link/")
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  })
  .catch(function(error) {
    console.log(error);
  });

Приведенный выше код печатает массив объектов в консоли браузера. Давайте сейчас имеем дело с ошибкой. Получить версию правды, чем мыpolyfillСложнее, но нетрудно добиться такого же поведения.FetchОбъект ответа имеет свойство, логическое значение с именем **"ok"**. Это логическое значение установлено вtrue, установлен вfalse. Разработчик может проверить логическое значение и изменить его, выдав ошибкуPromise обработчик. Это использование фактическогоFetchСпособы проверки статуса:

fetch("https://academy.valentinog.com/api/link/")
  .then(function(response) {
    if (!response.ok) {
      throw Error(response.statusText);
    }
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  })
  .catch(function(error) {
    console.log(error);
  });

Как видите, есть еще один"statusText". Кажется, легко реализовать в объекте Response"ok"а также"statusText". Когда сервер успешно отвечает,response.okдляtrue:

  • Код состояния равен или меньше 200
  • Код состояния менее 300

рефакторингResponseметод следующим образом:


function Response(response) {
  this.response = response.response;
  this.ok = response.status >= 200 && response.status < 300;
  this.statusText = response.statusText;
}

Нет необходимости создавать "statusText", так как это былоXMLHttpRequestОбъект ответа возвращается. Это означает, что вам нужно передать весь ответ только при создании пользовательского ответа.

function fetch(url) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    request.open("GET", url);
    request.onload = function() {
      // 前面:
      // var response = new Response(this.response);
      // 现在: pass the entire response
      const response = new Response(this);
      resolve(response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    request.send();
  });
}

Но теперь возникла проблема с нашим полифиллом. Он принимает один параметр "url«И только выдал егоGETпросить. Исправить это должно быть легко. Во-первых, мы можем принять второе имяrequestInitпараметр. Затем на основе этого параметра мы можем создать новый объект запроса:

  • По умолчанию делается GET-запрос
  • Если предоставлено, используйте requestInitbody,methodа такжеheaders

Сначала создайтеbody,methodа такжеheadersсвойства новогоRequestфункционируют следующим образом:

function Request(requestInit) {
  this.method = requestInit.method || "GET";
  this.body = requestInit.body;
  this.headers = requestInit.headers;
}

Но помимо этого мы можем добавить минимальную логику для установки заголовков запроса

function fetch(url, requestInit) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    const requestConfiguration = new Request(requestInit || {});
    request.open(requestConfiguration.method, url);
    request.onload = function() {
      const response = new Response(this);
      resolve(response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    // 设置 headers
    for (const header in requestConfiguration.headers) {
      request.setRequestHeader(header, requestConfiguration.headers[header]);
    }
    // more soon
  });
}

setRequestHeaderдопустимыйXMLHttpRequestиспользуется непосредственно на объекте.headersВажно для настройки запросов AJAX. В большинстве случаев вы можете захотетьheadersустановить вapplication/jsonили токен аутентификации.

  • Пустой запрос, если нет тела
  • Запрос с некоторой полезной нагрузкойbodyкоторый предоставил
function fetch(url, requestInit) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    const requestConfiguration = new Request(requestInit || {});
    request.open(requestConfiguration.method, url);
    request.onload = function() {
      const response = new Response(this);
      resolve(response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    // Set headers on the request
    for (const header in requestConfiguration.headers) {
      request.setRequestHeader(header, requestConfiguration.headers\[header\]);
    }
    // If there's a body send it
    // If not send an empty GET request
    requestConfiguration.body && request.send(requestConfiguration.body);
    requestConfiguration.body || request.send();
  });
}

Вот полный код:

"use strict";

window.fetch = fetch;

function Response(response) {
  this.response = response.response;
  this.ok = response.status >= 200 && response.status < 300;
  this.statusText = response.statusText;
}

Response.prototype.json = function() {
  return JSON.parse(this.response);
};

function Request(requestInit) {
  this.method = requestInit.method || "GET";
  this.body = requestInit.body;
  this.headers = requestInit.headers;
}

function fetch(url, requestInit) {
  return new Promise(function(resolve, reject) {
    const request = new XMLHttpRequest();
    const requestConfiguration = new Request(requestInit || {});
    request.open(requestConfiguration.method, url);
    request.onload = function() {
      const response = new Response(this);
      resolve(response);
    };
    request.onerror = function() {
      reject("Network error!");
    };
    for (const header in requestConfiguration.headers) {
      request.setRequestHeader(header, requestConfiguration.headers[header]);
    }
    requestConfiguration.body && request.send(requestConfiguration.body);
    requestConfiguration.body || request.send();
  });
}

const link = {
  title: "Building a Fetch Polyfill From Scratch",
  url: "https://www.valentinog.com/fetch-api/"
};

const requestInit = {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(link)
};

fetch("https://academy.valentinog.com/api/link/create/", requestInit)
  .then(function(response) {
    if (!response.ok) {
      throw Error(response.statusText);
    }
    return response.json();
  })
  .then(function(json) {
    console.log(json);
  })
  .catch(function(error) {
    console.log(error);
  });

Реальная реализация Fetch API намного сложнее и поддерживает расширенные функции. Мы только поцарапали поверхность. Код можно улучшить, например, добавивheadersЛогика может существовать независимо от метода.

Кроме того, есть много возможностей для добавления новых функций: поддержкаPUTа такжеDELETEи многие другие функции, которые возвращают ответы в разных форматах. Если вы хотите увидеть более сложный полифил API для извлечения данных, ознакомьтесь с этим сообщением инженера на Github.whatwg-fetch. вы найдете нашpolyfillЕсть много общего.

Суммировать

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

Теперь мы можем создавать элегантные JS-приложения и получать необходимые данные в фоновом режиме.XMLHttpRequest— это старый добрый устаревший API для выполнения HTTP-запросов, который все еще используется сегодня, но в другой форме:Fetch API.

Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.

оригинал:GitHub.com/Валентино Г.А.…

общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.