Как получить данные с сайта javascript
Перейти к содержимому

Как получить данные с сайта javascript

  • автор:

Fetch

JavaScript может отправлять сетевые запросы на сервер и подгружать новую информацию по мере необходимости.

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

  • Отправить заказ,
  • Загрузить информацию о пользователе,
  • Запросить последние обновления с сервера,
  • …и т.п.

Для сетевых запросов из JavaScript есть широко известный термин «AJAX» (аббревиатура от Asynchronous JavaScript And XML). XML мы использовать не обязаны, просто термин старый, поэтому в нём есть это слово. Возможно, вы его уже где-то слышали.

Есть несколько способов делать сетевые запросы и получать информацию с сервера.

Метод fetch() — современный и очень мощный, поэтому начнём с него. Он не поддерживается старыми (можно использовать полифил), но поддерживается всеми современными браузерами.

let promise = fetch(url, [options])
  • url – URL для отправки запроса.
  • options – дополнительные параметры: метод, заголовки и так далее.

Без options это простой GET-запрос, скачивающий содержимое по адресу url .

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

Процесс получения ответа обычно происходит в два этапа.

Во-первых, promise выполняется с объектом встроенного класса Response в качестве результата, как только сервер пришлёт заголовки ответа.

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

Промис завершается с ошибкой, если fetch не смог выполнить HTTP-запрос, например при ошибке сети или если нет такого сайта. HTTP-статусы 404 и 500 не являются ошибкой.

Мы можем увидеть HTTP-статус в свойствах ответа:

  • status – код статуса HTTP-запроса, например 200.
  • ok – логическое значение: будет true , если код HTTP-статуса в диапазоне 200-299.
let response = await fetch(url); if (response.ok) < // если HTTP-статус в диапазоне 200-299 // получаем тело ответа (см. про этот метод ниже) let json = await response.json(); >else

Во-вторых, для получения тела ответа нам нужно использовать дополнительный вызов метода.

Response предоставляет несколько методов, основанных на промисах, для доступа к телу ответа в различных форматах:

  • response.text() – читает ответ и возвращает как обычный текст,
  • response.json() – декодирует ответ в формате JSON,
  • response.formData() – возвращает ответ как объект FormData (разберём его в следующей главе),
  • response.blob() – возвращает объект как Blob (бинарные данные с типом),
  • response.arrayBuffer() – возвращает ответ как ArrayBuffer (низкоуровневое представление бинарных данных),
  • помимо этого, response.body – это объект ReadableStream, с помощью которого можно считывать тело запроса по частям. Мы рассмотрим и такой пример несколько позже.

Например, получим JSON-объект с последними коммитами из репозитория на GitHub:

let url = 'https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'; let response = await fetch(url); let commits = await response.json(); // читаем ответ в формате JSON alert(commits[0].author.login);

То же самое без await , с использованием промисов:

fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits') .then(response => response.json()) .then(commits => alert(commits[0].author.login));

Для получения ответа в виде текста используем await response.text() вместо .json() :

let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); let text = await response.text(); // прочитать тело ответа как текст alert(text.slice(0, 80) + '. ');

В качестве примера работы с бинарными данными, давайте запросим и выведем на экран логотип спецификации «fetch» (см. главу Blob, чтобы узнать про операции с Blob ):

let response = await fetch('/article/fetch/logo-fetch.svg'); let blob = await response.blob(); // скачиваем как Blob-объект // создаём let img = document.createElement('img'); img.style = 'position:fixed;top:10px;left:10px;width:100px'; document.body.append(img); // выводим на экран img.src = URL.createObjectURL(blob); setTimeout(() => < // прячем через три секунды img.remove(); URL.revokeObjectURL(img.src); >, 3000);

Мы можем выбрать только один метод чтения ответа.

Если мы уже получили ответ с response.text() , тогда response.json() не сработает, так как данные уже были обработаны.

let text = await response.text(); // тело ответа обработано let parsed = await response.json(); // ошибка (данные уже были обработаны)

Заголовки ответа

Заголовки ответа хранятся в похожем на Map объекте response.headers .

Это не совсем Map , но мы можем использовать такие же методы, как с Map , чтобы получить заголовок по его имени или перебрать заголовки в цикле:

let response = await fetch('https://api.github.com/repos/javascript-tutorial/en.javascript.info/commits'); // получить один заголовок alert(response.headers.get('Content-Type')); // application/json; charset=utf-8 // перебрать все заголовки for (let [key, value] of response.headers) < alert(`$= $`); >

Заголовки запроса

Для установки заголовка запроса в fetch мы можем использовать опцию headers . Она содержит объект с исходящими заголовками, например:

let response = fetch(protectedUrl, < headers: < Authentication: 'secret' >>);

Есть список запрещённых HTTP-заголовков, которые мы не можем установить:

  • Accept-Charset , Accept-Encoding
  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Connection
  • Content-Length
  • Cookie , Cookie2
  • Date
  • DNT
  • Expect
  • Host
  • Keep-Alive
  • Origin
  • Referer
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • Via
  • Proxy-*
  • Sec-*

Эти заголовки обеспечивают достоверность данных и корректную работу протокола HTTP, поэтому они контролируются исключительно браузером.

POST-запросы

Для отправки POST -запроса или запроса с другим методом, нам необходимо использовать fetch параметры:

  • method – HTTP метод, например POST ,
  • body – тело запроса, одно из списка:
    • строка (например, в формате JSON),
    • объект FormData для отправки данных как form/multipart ,
    • Blob / BufferSource для отправки бинарных данных,
    • URLSearchParams для отправки данных в кодировке x-www-form-urlencoded , используется редко.

    Чаще всего используется JSON.

    Например, этот код отправляет объект user как JSON:

    let user = < name: 'John', surname: 'Smith' >; let response = await fetch('/article/fetch/post/user', < method: 'POST', headers: < 'Content-Type': 'application/json;charset=utf-8' >, body: JSON.stringify(user) >); let result = await response.json(); alert(result.message);

    Заметим, что так как тело запроса body – строка, то заголовок Content-Type по умолчанию будет text/plain;charset=UTF-8 .

    Но, так как мы посылаем JSON, то используем параметр headers для отправки вместо этого application/json , правильный Content-Type для JSON.

    Отправка изображения

    Мы можем отправить бинарные данные при помощи fetch , используя объекты Blob или BufferSource .

    В этом примере есть элемент , на котором мы можем рисовать движением мыши. При нажатии на кнопку «Отправить» изображение отправляется на сервер:

        

    Заметим, что здесь нам не нужно вручную устанавливать заголовок Content-Type , потому что объект Blob имеет встроенный тип ( image/png , заданный в toBlob ). При отправке объектов Blob он автоматически становится значением Content-Type .

    Функция submit() может быть переписана без async/await , например, так:

    function submit() < canvasElem.toBlob(function(blob) < fetch('/article/fetch/post/image', < method: 'POST', body: blob >) .then(response => response.json()) .then(result => alert(JSON.stringify(result, null, 2))) >, 'image/png'); >

    Итого

    Типичный запрос с помощью fetch состоит из двух операторов await :

    let response = await fetch(url, options); // завершается с заголовками ответа let result = await response.json(); // читать тело ответа в формате JSON
    fetch(url, options) .then(response => response.json()) .then(result => /* обрабатываем результат */)
    • response.status – HTTP-код ответа,
    • response.ok – true , если статус ответа в диапазоне 200-299.
    • response.headers – похожий на Map объект с HTTP-заголовками.

    Методы для получения тела ответа:

    • response.text() – возвращает ответ как обычный текст,
    • response.json() – декодирует ответ в формате JSON,
    • response.formData() – возвращает ответ как объект FormData (кодировка form/multipart, см. следующую главу),
    • response.blob() – возвращает объект как Blob (бинарные данные с типом),
    • response.arrayBuffer() – возвращает ответ как ArrayBuffer (низкоуровневые бинарные данные),

    Опции fetch , которые мы изучили на данный момент:

    • method – HTTP-метод,
    • headers – объект с запрашиваемыми заголовками (не все заголовки разрешены),
    • body – данные для отправки (тело запроса) в виде текста, FormData , BufferSource , Blob или UrlSearchParams .

    В следующих главах мы рассмотрим больше параметров и вариантов использования fetch .

    Задачи

    Получите данные о пользователях GitHub

    Создайте асинхронную функцию getUsers(names) , которая получает на вход массив логинов пользователей GitHub, запрашивает у GitHub информацию о них и возвращает массив объектов-пользователей.

    Информация о пользователе GitHub с логином USERNAME доступна по ссылке: https://api.github.com/users/USERNAME .

    В песочнице есть тестовый пример.

    1. На каждого пользователя должен приходиться один запрос fetch .
    2. Запросы не должны ожидать завершения друг друга. Надо, чтобы данные приходили как можно быстрее.
    3. Если какой-то запрос завершается ошибкой или оказалось, что данных о запрашиваемом пользователе нет, то функция должна возвращать null в массиве результатов.

    Чтобы получить сведения о пользователе, нам нужно вызвать fetch(‘https://api.github.com/users/USERNAME’) .

    Если ответ приходит cо статусом 200 , то вызываем метод .json() , чтобы прочитать JS-объект.

    А если запрос завершается ошибкой или код статуса в ответе отличен от 200, то мы просто возвращаем null в массиве результатов.

    async function getUsers(names) < let jobs = []; for(let name of names) < let job = fetch(`https://api.github.com/users/$`).then( successResponse => < if (successResponse.status != 200) < return null; >else < return successResponse.json(); >>, failResponse => < return null; >); jobs.push(job); > let results = await Promise.all(jobs); return results; >

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

    Если бы мы использовали await Promise.all(names.map(name => fetch(. ))) и вызывали бы .json() на результатах запросов, то пришлось бы ждать, пока завершатся все из них. Вызывая .json() сразу после каждого fetch , мы добились того, что считывание присланных по каждому запросу данных происходит независимо от других запросов.

    Это пример того, как относительно низкоуровневое Promise API может быть полезным, даже если мы в основном используем async/await в коде.

    Получение данных с помощью JavaScript Fetch API

    Было время, когда для выполнения запросов API использовался XMLHttpRequest. Он не поддерживал промисов и не создавал чистый код JavaScript. Также можно было использовать jQuery, который предоставляет более чистый синтаксис jQuery.ajax().

    Теперь у JavaScript есть встроенный способ выполнения запросов API. Это новый стандарт Fetch API, который поддерживает промисы и также включает в себя множество других функций.

    В этом пошаговом руководстве вы научитесь создавать запросы GET и POST с помощью Fetch API.

    Требования

    • Последняя версия Node, установленная на вашем компьютере. Чтобы установить Node в macOS, выполните руководство Установка Node.js и настройка локальной среды разработки в macOS.
    • Базовые навыки создания кода JavaScript.
    • Умение использовать промисы в JavaScript. Читайте мануал Как работают промисы в JavaScript.

    1: Основы синтаксиса Fetch API

    Чтобы использовать Fetch API, вызовите метод fetch, который принимает URL-адрес API в качестве параметра:

    fetch(url)

    После метода fetch() включите метод промиса then():

    .then(function() < >)

    Метод fetch() возвращает промис. Если он вернул resolve, выполняется функция в методе then(). Эта функция содержит код для обработки данных, полученных от API.

    Под методом then() включите метод catch():

    .catch(function() < >);

    API, который вы вызываете с помощью fetch(), может быть недоступен или при его вызове могут возникнуть ошибки. Если это произойдет, он вернет промис reject. Метод catch используется для обработки reject. Код внутри catch() будет выполнен, если при вызове API по вашему выбору возникнет ошибка.

    В итоге базовый код Fetch API будет выглядеть так:

    fetch(url) .then(function() < >) .catch(function() < >);

    Познакомившись с простейшим синтаксисом Fetch API, вы можете перейти к использованию fetch() в реальном API.

    2: Получение данных из API через Get-запрос

    Следующие примеры кода основаны на Random User API. С помощью этого API можно получить данные десяти пользователей и отобразить их на странице с помощью простейшего JavaScript.

    Идея нашего примера состоит в том, чтобы извлечь все данные из Random User API и отобразить их в качестве элементов списка authors. Начнем с создания HTML-файла, в который поместим заголовок и неупорядоченный список с id authors:

    Authors

    Добавьте теги script в конец HTML-файла и используйте селектор DOM, чтобы захватить ul. Также используйте getElementById с authors в качестве аргумента. Помните, что authors – это идентификатор ранее созданного ul.

      

    После этого создайте постоянную переменную по имени url. Она будет содержать URL-адрес API, который вернет десять случайных пользователей:

    const url = 'https://randomuser.me/api/?results=10';

    Написав ul и url, мы можем добавить функции, которые будут использоваться для создания элементов списка. Создайте функцию createNode, которая принимает параметр оп имени element:

    function createNode(element)

    Позже, при вызове createNode, нужно будет передать имя фактического HTML-элемента, который нужно создать.

    Внутри функции поместите оператор return, который возвращает элемент, используя document.createElement():

    function createNode(element)

    Также нам понадобится функция по имени append, которая принимает два параметра: parent и el.

    function append(parent, el)

    Эта функция добавит el к родительскому элементу с помощью document.createElement:

    function append(parent, el)

    Функции createNode и append готовы к работе. Используя Fetch API, вызовите Random User API с помощью fetch() и URL-адресом в качестве аргумента:

    fetch(url)
    fetch(url) .then(function(data) < >) >) .catch(function(error) < >);

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

    Добавим метод then(), который будет содержать функцию с параметром resp:

    fetch(url) .then((resp) => )

    Параметр resp принимает значение объекта, возвращенного из fetch(url). Используйте метод json() для преобразования resp в данные JSON:

    fetch(url) .then((resp) => resp.json())

    Данные JSON еще нужно обработать. Давайте добавим еще один оператор then() с функцией, у которой будет аргумент data:

    .then(function(data) < >) >)

    В этой функции создайте переменную по имени authors со значением data.results:

    .then(function(data) < let authors = data.results;

    Для каждого автора в списке authors мы создадим элемент списка, который покажет их имя и изображение. Этого можно достичь с помощью метода map():

    let authors = data.results; return authors.map(function(author) < >)

    В своей функции map создайте переменную по имени li, которая будет ​​равна createNode с HTML-элементом li в качестве аргумента:

    return authors.map(function(author) < let li = createNode('li'); >)

    Повторите этот фрагмент, чтобы создать элемент span и элемент img:

    let li = createNode('li'); let img = createNode('img'); let span = createNode('span');

    API предлагает имя автора и изображение, которое сопровождает имя. Установите в img.src картинку автора:

    let img = createNode('img'); let span = createNode('span'); img.src = author.picture.medium;

    Элемент span должен содержать имя и фамилию автора. Свойство innerHTML и интерполяция строк позволят вам добавить эти данные:

    img.src = author.picture.medium; span.innerHTML = `$ $`;

    Создав элемент изображения и списка через span, вы можете использовать ранее созданную функцию append для отображения этих элементов на странице:

    append(li, img); append(li, span); append(ul, li);

    После завершения обеих функций then() вы можете добавить catch(). Эта функция будет записывать потенциальную ошибку в консоль:

    .catch(function(error) < console.log(error); >);

    Полный код созданного запроса имеет такой вид:

    function createNode(element) < return document.createElement(element); >function append(parent, el) < return parent.appendChild(el); >const ul = document.getElementById('authors'); const url = 'https://randomuser.me/api/?results=10'; fetch(url) .then((resp) => resp.json()) .then(function(data) < let authors = data.results; return authors.map(function(author) < let li = createNode('li'); let img = createNode('img'); let span = createNode('span'); img.src = author.picture.medium; span.innerHTML = `$$`; append(li, img); append(li, span); append(ul, li); >) >) .catch(function(error) < console.log(error); >);

    Только что вы успешно выполнили GET-запрос, используя Random User API и Fetch API. На следующем шаге вы узнаете, как выполнять запросы POST.

    3: Обработка POST-запросов

    По умолчанию Fetch использует запросы GET, но, конечно, вы можете использовать все другие типы запросов, изменять заголовки и отправлять данные. Для этого нужно установить свой объект и передать его в качестве второго аргумента функции fetch.

    Перед созданием POST-запроса создайте данные, которые вы хотите отправить в API. Допустим, это будет объект data с ключом name и значением 8host (при желании укажите другое имя):

    const url = 'https://randomuser.me/api'; let data =

    Обязательно укажите постоянную переменную, которая содержит ссылку на Random User API.

    Чтобы создать POST-запрос, нам необходимо указать это явно. Создайте объект fetchData:

    let fetchData =

    Этот объект должен включать три ключа: method, body и headers. Ключ method должен иметь значение ‘POST’; body должен быть равен только что созданному объекту data; headers должны иметь значение new Headers().

    let fetchData =

    Интерфейс Headers – это свойство Fetch API, которое позволяет выполнять различные действия с заголовками HTTP-запросов и ответов.

    Написав этот код, вы можете выполнить POST-запрос с помощью Fetch API. Включите url и fetchData в качестве аргументов POST-запроса fetch:

    fetch(url, fetchData)

    Функция then() будет содержать код, который обрабатывает ответ, полученный от сервера Random User API:

    fetch(url, fetchData) .then(function() < // Обрабатывает полученный от сервера ответ >);

    Вместо создания объекта fetchData вы можете использовать конструктор запроса для создания объекта запроса. Для этого создайте переменную по имени request:

    const url = 'https://randomuser.me/api'; let data = < name: 'Sara' >var request =

    Переменная request должна быть равна new Request. Новая конструкция Request принимает два аргумента: URL-адрес API (url) и объект. Объект (как и fetchData) должен включать ключи method, body и headers:

    var request = new Request(url, < method: 'POST', body: data, headers: new Headers() >);

    Теперь request можно использовать как единственный аргумент для fetch(), поскольку он также включает URL-адрес API:

    fetch(request) .then(function() < // обработка ответа, полученного от API >)

    В итоге код будет выглядеть так:

    const url = 'https://randomuser.me/api'; let data = < name: 'Sara' >var request = new Request(url, < method: 'POST', body: data, headers: new Headers() >); fetch(request) .then(function() < // обработка ответа, полученного от API >)

    Теперь вы знаете два метода создания и выполнения запросов POST с помощью Fetch API.

    Заключение

    Пока что Fetch API еще не поддерживается всеми браузерами, однако уже сейчас это отличная альтернатива XMLHttpRequest.

    Как получить данные с сервера на чистом js?

    Дело в том что данные XMLHttpRequest можно будет получить в onload методе. В вашем случае вы отправляете запрос и тут же хотите ответ это не php а JavaScript он хоть и однопоточный но все же асинхронный. Хотите синхронно то поставьте 3 параметр в open false.

    request.open("POST", url, false);

    Отслеживать
    ответ дан 7 июл 2020 в 19:29
    Aziz Umarov Aziz Umarov
    22.6k 2 2 золотых знака 10 10 серебряных знаков 33 33 бронзовых знака
    Спасибо, помогло
    7 июл 2020 в 20:05
    Рад помочь. Изучайте дальше
    7 июл 2020 в 20:19

    Не буду минусовать, но это плохое решение, т.к. "подвесит" весь скрипт. ТС лично оно подходит, но в нормальных системах его не нужно использовать. Хорошее решение - у @MoloF ru.stackoverflow.com/a/1150225/287469

    8 июл 2020 в 9:30

    Речь идёт не о хорошем решении. А о ситуации. По сути надо обрабатывать onload чтобы невешать скрипт я это написал

    Получение данных с сервера

    Другой очень распространённой задачей в современных веб-сайтах и приложениях является получение отдельных элементов данных с сервера для обновления разделов веб-страницы без необходимости загрузки всей новой страницы. Эта, казалось бы, небольшая деталь оказала огромное влияние на производительность и поведение сайтов, поэтому в этой статье мы объясним концепцию и рассмотрим технологии, которые делают это возможным, например XMLHttpRequest и API Fetch.

    Необходимые условия: Основы JavaScript (см. первые шаги, структурные элементы, объекты JavaScript), основы клиентских API
    Задача: Узнать, как извлекать данные с сервера и использовать их для обновления содержимого веб-страницы.

    В чем проблема?

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

    A basic representation of a web site architecture

    Проблема с этой моделью заключается в том, что всякий раз, когда вы хотите обновить любую часть страницы, например, чтобы отобразить новый набор продуктов или загрузить новую страницу, вам нужно снова загрузить всю страницу. Это очень расточительно и приводит к плохому пользовательскому опыту, особенно по мере того, как страницы становятся все более сложными.

    Появление Ajax

    Это привело к созданию технологий, позволяющих веб-страницам запрашивать небольшие фрагменты данных (например, HTML, XML, JSON или обычный текст) и отображать их только при необходимости, помогая решать проблему, описанную выше.

    Это достигается с помощью таких API, как XMLHttpRequest или - более новой - Fetch API. Эти технологии позволяют веб-страницам напрямую обрабатывать запросы HTTP для определённых ресурсов, доступных на сервере, и форматировать результирующие данные по мере необходимости перед их отображением.

    Примечание: Вначале эта общая техника была известна как Асинхронный JavaScript и XML (Ajax), поскольку она, как правило, использовала XMLHttpRequest для запроса данных XML. В наши дни это обычно не так (вы, скорее всего, будете использовать XMLHttpRequest или Fetch для запроса JSON), но результат все тот же, и термин «Ajax» по-прежнему часто используется для описания этой техники.

    A simple modern architecture for web sites

    Модель Ajax предполагает использование веб-API в качестве прокси для более разумного запроса данных, а не просто для того, чтобы браузер перезагружал всю страницу. Давайте подумаем о значении этого:

    1. Перейдите на один из ваших любимых сайтов, богатых информацией, таких как Amazon, YouTube, CNN и т.д., и загрузите его.
    2. Теперь найдите что-нибудь, например, новый продукт. Основной контент изменится, но большая часть информации, подобной заголовку, нижнему колонтитулу, навигационному меню и т. д., останется неизменной.

    Это действительно хорошо, потому что:

    • Обновления страницы намного быстрее, и вам не нужно ждать перезагрузки страницы, а это означает, что сайт работает быстрее и воспринимается более отзывчивым.
    • Меньше данных загружается при каждом обновлении, что означает меньшее потребление пропускной способности. Это не может быть такой большой проблемой на рабочем столе в широкополосном подключении, но это серьёзная проблема на мобильных устройствах и в развивающихся странах, которые не имеют повсеместного быстрого интернет-сервиса.

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

    A basic web app data flow architecture

    Основной запрос Ajax

    Давайте посмотрим, как обрабатывается такой запрос, используя как XMLHttpRequest , так и Fetch. В этих примерах мы будем запрашивать данные из нескольких текстовых файлов и использовать их для заполнения области содержимого.

    Этот набор файлов будет действовать как наша поддельная база данных; в реальном приложении мы с большей вероятностью будем использовать серверный язык, такой как PHP, Python или Node, чтобы запрашивать наши данные из базы данных. Здесь, однако, мы хотим сохранить его простым и сосредоточиться на стороне клиента.

    XMLHttpRequest

    XMLHttpRequest (который часто сокращается до XHR) является довольно старой технологией сейчас - он был изобретён Microsoft в конце 1990-х годов и уже довольно долго стандартизирован в браузерах.

    1. Чтобы начать этот пример, создайте локальную копию ajax-start.html и четырёх текстовых файлов - verse1.txt, verse2.txt, verse3.txt и verse4.txt - в новом каталоге на вашем компьютере. В этом примере мы загрузим другое стихотворение (который вы вполне можете распознать) через XHR, когда он будет выбран в выпадающем меню.
    2. Внутри элемента добавьте следующий код. В нем хранится ссылка на элементы и в переменных и определяется onchange обработчика событий, так что, когда значение select изменяется, его значение передаётся вызываемой функции updateDisplay() в качестве параметра.

    var verseChoose = document.querySelector("select"); var poemDisplay = document.querySelector("pre"); verseChoose.onchange = function ()  var verse = verseChoose.value; updateDisplay(verse); >; 
    function updateDisplay(verse) > 
    = verse.replace(" ", ""); verse = verse.toLowerCase(); var url = verse + ".txt"; 
    var request = new XMLHttpRequest(); 
    .open("GET", url); 
    .responseType = "text"; 
    .onload = function ()  poemDisplay.textContent = request.response; >; 
    .send(); 
    updateDisplay("Verse 1"); verseChoose.value = "Verse 1"; 

    Обслуживание вашего примера с сервера

    Некоторые браузеры (включая Chrome) не будут запускать запросы XHR, если вы просто запускаете пример из локального файла. Это связано с ограничениями безопасности (для получения дополнительной информации о безопасности в Интернете, ознакомьтесь с Website security).

    Чтобы обойти это, нам нужно протестировать пример, запустив его через локальный веб-сервер. Чтобы узнать, как это сделать, прочитайте Как настроить локальный тестовый сервер?

    Fetch

    API-интерфейс Fetch - это, в основном, современная замена XHR - недавно он был представлен в браузерах для упрощения асинхронных HTTP-запросов в JavaScript, как для разработчиков, так и для других API, которые строятся поверх Fetch.

    Давайте преобразуем последний пример, чтобы использовать Fetch!

    1. Сделайте копию своего предыдущего готового каталога примеров. (Если вы не работали над предыдущим упражнением, создайте новый каталог и внутри него создайте копии xhr-basic.html и четырёх текстовых файлов — verse1.txt, verse2.txt, verse3.txt и verse4.txt.)
    2. Внутри функции updateDisplay() найдите код XHR:

    var request = new XMLHttpRequest(); request.open("GET", url); request.responseType = "text"; request.onload = function ()  poemDisplay.textContent = request.response; >; request.send(); 
    fetch(url).then(function (response)  response.text().then(function (text)  poemDisplay.textContent = text; >); >); 
    Итак, что происходит в коде Fetch?

    Прежде всего, мы вызываем метод fetch() , передавая ему URL-адрес ресурса, который мы хотим получить. Это современный эквивалент request.open() в XHR, плюс вам не нужен эквивалент .send() .

    После этого вы можете увидеть метод .then() , прикреплённый в конец fetch() - этот метод является частью Promises - современная функция JavaScript для выполнения асинхронных операций. fetch() возвращает промис, который разрешает ответ, отправленный обратно с сервера, - мы используем .then() для запуска некоторого последующего кода после того, как промис будет разрешено, что является функцией, которую мы определили внутри неё. Это эквивалент обработчика события onload в XHR-версии.

    Эта функция автоматически передаёт ответ от сервера в качестве параметра, когда обещает fetch() . Внутри функции мы берём ответ и запускаем его метод text() (en-US), который в основном возвращает ответ как необработанный текст. Это эквивалент request.responseType = 'text' в версии XHR.

    Вы увидите, что text() также возвращает промис, поэтому мы привязываем к нему другой .then() , внутри которого мы определяем функцию для получения необработанного текста, который выполняет text() .

    Внутри функции внутреннего промиса мы делаем то же самое, что и в версии XHR, - устанавливаем текстовое содержимое в текстовое значение.

    Помимо промисов

    Промисы немного запутывают первый раз, когда вы их встречаете, но не беспокойтесь об этом слишком долго. Через некоторое время вы привыкнете к ним, особенно, когда вы узнаете больше о современных JavaScript-API. Большинство из них в большей степени основаны на промисах.

    Давайте посмотрим на структуру промисов сверху, чтобы увидеть, можем ли мы ещё немного понять это:

    fetch(url).then(function (response)  response.text().then(function (text)  poemDisplay.textContent = text; >); >); 

    В первой строке говорится: «Получить ресурс, расположенный по адресу url» (fetch(url) ) и «затем запустить указанную функцию, когда промис будет разрешено» ( .then(function() < . >) ). «Resolve» означает «завершить выполнение указанной операции в какой-то момент в будущем». Указанная операция в этом случае заключается в извлечении ресурса с указанного URL (с использованием HTTP-запроса) и возврата ответа для нас, чтобы что-то сделать.

    Фактически, функция, переданная в then() , представляет собой кусок кода, который не запускается немедленно - вместо этого он будет работать в какой-то момент в будущем, когда ответ будет возвращён. Обратите внимание, что вы также можете сохранить своё промис в переменной и цепочку .then() вместо этого. Ниже код будет делать то же самое:

    var myFetch = fetch(url); myFetch.then(function (response)  response.text().then(function (text)  poemDisplay.textContent = text; >); >); 

    Поскольку метод fetch() возвращает промис, который разрешает HTTP-ответ, любая функция, которую вы определяете внутри .then() , прикованная к концу, будет автоматически передаваться как параметр. Вы можете вызвать параметр, который вам нравится - приведённый ниже пример будет работать:

    fetch(url).then(function (dogBiscuits)  dogBiscuits.text().then(function (text)  poemDisplay.textContent = text; >); >); 

    Но имеет смысл называть параметр тем, что описывает его содержимое!

    Теперь давайте сосредоточимся только на функции:

    function(response)  response.text().then(function(text)  poemDisplay.textContent = text; >); > 

    Объект ответа имеет метод text() (en-US), который берёт необработанные данные, содержащиеся в теле ответа, и превращает его в обычный текст, который является форматом, который мы хотим в нем А также возвращает промис (который разрешает полученную текстовую строку), поэтому здесь мы используем другой .then() , внутри которого мы определяем другую функцию, которая диктует что мы хотим сделать с этой текстовой строкой. Мы просто устанавливаем свойство textContent элемента нашего стихотворения равным текстовой строке, так что это получается довольно просто.

    Также стоит отметить, что вы можете напрямую связывать несколько блоков промисов ( .then() , но есть и другие типы) на конце друг друга, передавая результат каждого блока следующему блоку по мере продвижения по цепочке , Это делает промисы очень мощными.

    Следующий блок делает то же самое, что и наш оригинальный пример, но написан в другом стиле:

    fetch(url) .then(function (response)  return response.text(); >) .then(function (text)  poemDisplay.textContent = text; >); 

    Многие разработчики любят этот стиль больше, поскольку он более плоский и, возможно, легче читать для более длинных цепочек промисов - каждое последующее промис приходит после предыдущего, а не внутри предыдущего (что может стать громоздким). Единственное отличие состоит в том, что мы должны были включить оператор return перед response.text() , чтобы заставить его передать результат в следующую ссылку в цепочке.

    Какой механизм следует использовать?

    Это действительно зависит от того, над каким проектом вы работаете. XHR существует уже давно и имеет отличную кросс-браузерную поддержку. Fetch and Promises, с другой стороны, являются более поздним дополнением к веб-платформе, хотя они хорошо поддерживаются в браузере, за исключением Internet Explorer и Safari (которые на момент написания Fetch были доступны в своём предварительный просмотр технологии).

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

    Вам действительно нужно учиться - Fetch станет более популярным, так как Internet Explorer отказывается от использования (IE больше не разрабатывается, в пользу нового браузера Microsoft Edge), но вам может понадобиться XHR ещё некоторое время.

    Более сложный пример

    Чтобы завершить статью, мы рассмотрим несколько более сложный пример, который показывает более интересные применения Fetch. Мы создали образец сайта под названием The Can Store - это вымышленный супермаркет, который продаёт только консервы. Вы можете найти этот пример в прямом эфире на GitHub и посмотреть исходный код.

    A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column.

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

    Существует довольно много сложного кода, который включает фильтрацию продуктов по категориям и поисковым запросам, манипулирование строками, чтобы данные отображались правильно в пользовательском интерфейсе и т.д. Мы не будем обсуждать все это в статье, но вы можете найти обширные комментарии в коде (см. can-script.js).

    Однако мы объясним код Fetch.

    Первый блок, который использует Fetch, можно найти в начале JavaScript:

    fetch("products.json").then(function (response)  if (response.ok)  response.json().then(function (json)  products = json; initialize(); >); > else  console.log( "Network request for products.json failed with response " + response.status + ": " + response.statusText, ); > >); 

    Это похоже на то, что мы видели раньше, за исключением того, что второй промис находится в условном выражении. В этом случае мы проверяем, был ли возвращённый ответ успешным - свойство response.ok (en-US) содержит логическое значение, которое true , если ответ был в порядке (например, 200 meaning "OK") или false , если он не увенчался успехом.

    Если ответ был успешным, мы выполняем второй промис - на этот раз мы используем json() (en-US), а не text() (en-US), так как мы хотим вернуть наш ответ как структурированные данные JSON, а не обычный текст.

    Если ответ не увенчался успехом, мы выводим сообщение об ошибке в консоль, в котором сообщается о сбое сетевого запроса, который сообщает о статусе сети и описательном сообщении ответа (содержащемся в response.status (en-US) и response.statusText (en-US), соответственно). Конечно, полный веб-сайт будет обрабатывать эту ошибку более грациозно, отображая сообщение на экране пользователя и, возможно, предлагая варианты для исправления ситуации.

    Вы можете проверить сам случай отказа:

    1. Создание локальной копии файлов примеров (загрузка и распаковка the can-store ZIP file)
    2. Запустите код через веб-сервер (как описано выше, в Serving your example from a server)
    3. Измените путь к извлечённому файлу, например, «product.json» (т.е. убедитесь, что он написан неправильно)
    4. Теперь загрузите индексный файл в свой браузер (например, через localhost:8000 ) и посмотрите в консоли разработчика браузера. Вы увидите сообщение в строке «Запрос сети для продуктов.json не удалось с ответом 404: Файл не найден»

    Второй блок Fetch можно найти внутри функции fetchBlob() :

    fetch(url).then(function (response)  if (response.ok)  response.blob().then(function (blob)  objectURL = URL.createObjectURL(blob); showProduct(objectURL, product); >); > else  console.log( 'Network request for "' + product.name + '" image failed with response ' + response.status + ": " + response.statusText, ); > >); 

    Это работает во многом так же, как и предыдущий, за исключением того, что вместо использования json() (en-US) мы используем blob() (en-US) - в этом случае мы хотим вернуть наш ответ в виде файла изображения, а формат данных, который мы используем для этого - Blob - этот термин является аббревиатурой от« Binary Large Object »и может в основном использоваться для представляют собой большие файловые объекты, такие как изображения или видеофайлы.

    После того как мы успешно получили наш blob, мы создаём URL-адрес объекта, используя createObjectURL() . Это возвращает временный внутренний URL-адрес, указывающий на объект, указанный в браузере. Они не очень читаемы, но вы можете видеть, как выглядит, открывая приложение Can Store, Ctrl-/щёлкнуть правой кнопкой мыши по изображению и выбрать опцию «Просмотр изображения» (которая может немного отличаться в зависимости от того, какой браузер вы ). URL-адрес объекта будет отображаться внутри адресной строки и должен выглядеть примерно так:

    blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4

    Вызов: XHR версия the Can Store

    Мы хотели бы, чтобы вы решили преобразовать версию приложения Fetch для использования XHR в качестве полезной части практики. Возьмите копию ZIP файла и попробуйте изменить JavaScript, если это необходимо.

    Некоторые полезные советы:

    • Вы можете найти полезный справочный материал XMLHttpRequest .
    • Вам в основном нужно использовать тот же шаблон, что и раньше, в примере XHR-basic.html.
    • Однако вам нужно будет добавить обработку ошибок, которые мы показали вам в версии Fetch Can Store:
      • Ответ найден в request.response после того, как событие load запущено, а не в промисе then() .
      • О наилучшем эквиваленте Fetch's response.ok в XHR следует проверить, является ли request.status равным 200 или если request.readyState равно 4.
      • Свойства для получения статуса и сообщения состояния одинаковы, но они находятся на объекте request (XHR), а не в объекте response .

      Примечание: Если у вас есть проблемы с этим, не стесняйтесь сравнить свой код с готовой версией на GitHub (см. исходник здесь, а также см. это в действии).

      Резюме

      Это завершает нашу статью по извлечению данных с сервера. К этому моменту вы должны иметь представление о том, как начать работать как с XHR, так и с Fetch.

      Смотрите также

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

      • Введение в Ajax (en-US)
      • Применение Fetch
      • Promises
      • Работа с JSON данными
      • Обзор HTTP
      • Программирование веб-сайта на стороне сервера
      • Назад
      • Обзор: Client-side web APIs
      • Далее

      Found a content problem with this page?

      • Edit the page on GitHub.
      • Report the content issue.
      • View the source on GitHub.

      This page was last modified on 2 дек. 2023 г. by MDN contributors.

      Your blueprint for a better internet.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *