ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Извлечение данных из ReadableStream с помощью Fetch API

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы получить данные из ReadableStream, примените методы getReader() и read():

JS
Скопировать код
const reader = stream.getReader();
let chunks = [], decoder = new TextDecoder();

reader.read().then(function processData({ done, value }) {
  if (done) {
    console.log('Поток завершён, все фрагменты данных получены', decoder.decode(concat(chunks)));
    return;
  }
  chunks.push(value);
  reader.read().then(processData);
});

function concat(chunks) { // Объединяем части в одно целое
  return chunks.reduce((acc, chunk) => new Uint8Array([...acc, ...chunk]), new Uint8Array());
}

Используя этот код, вы будете рекурсивно вызывать read(), собирать обрывки данных и в конечном итоге, декодировать и выводить собранные данные.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Использование Fetch API с ReadableStream

Для выполнения API-запросов используйте метод fetch(). Чтобы обработать JSON используйте response.json(), для текстовых данных — response.text(), а для бинарных данных — response.arrayBuffer().

JS
Скопировать код
fetch('https://api.example.com/data')
  .then(response => response.json()) // Преобразуем ответ в JSON
  .then(data => console.log(data))
  .catch(error => console.error('Произошла ошибка:', error));

// Обработка данных в формате, отличном от JSON
fetch('https://api.example.com/data')
  .then(response => response.text()) // Получаем текстовую информацию
  .then(text => console.log(text))
  .catch(error => console.error('Произошла ошибка:', error));

// Работа с бинарными данными
fetch('https://api.example.com/binary-data')
  .then(response => response.arrayBuffer()) // Получаем массив байт
  .then(buffer => console.log(new Uint8Array(buffer)))
  .catch(error => console.error('Произошла ошибка:', error));

Интересно, что response.json(), response.text() и response.arrayBuffer() сами справляются с задачей собирания и декодирования данных.

Ручной парсинг ReadableStream для смельчаков

Парсинг ReadableStream вручную — это настоящее приключение. Воспользуйтесь getReader() для чтения данных. TextDecoder придёт вам на помощь в сборке и декодировании.

JS
Скопировать код
async function streamToString(stream) {
  const reader = stream.getReader();
  const decoder = new TextDecoder(); // Наш помощник — декодер
  let result = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    result += decoder.decode(value, { stream: true });
  }
  result += decoder.decode(); // Финальный шаг для получения данных
  return result;
}

streamToString(yourReadableStream)
  .then(str => JSON.parse(str))
  .then(data => console.log('Данные получены:', data))
  .catch(error => console.error('Ошибка при обработке данных:', error));

Управление ошибками и путь менее избитый

Всегда реализуйте обработку ошибок с помощью catch(). Экспериментируйте с разнообразными методами декодирования и создавайте собственные парсеры для работы с нестандартными типами данных.

JS
Скопировать код
fetch('https://api.example.com/data').then(response => {
  if (!response.ok) {
    throw new Error('Сервер вернул некорректный ответ');
  }
  return response.json();
})
.catch(error => {
  console.error('Произошла ошибка при запросе данных:', error);
});

Node.js работает иначе, предлагая stream и современный API stream/consumers для эффективной работы с потоками. Обратите внимание на TransformStream для преобразования данных, а также на поточные пайплайны.

Визуализация

Ваши действия с ReadableStream можно сравнить с игрой в ведро и кран.

Когда вы открываете "кран" с помощью stream.getReader()...

JS
Скопировать код
const reader = stream.getReader();

reader.read().then(({ value, done }) => {
  if (done) {
    console.log("Поток завершён. Данные собраны!");
  } else {
    console.log(`Получена новая порция данных:`, value);
  }
});

... и затем закрываете его:

Markdown
Скопировать код
reader.cancel(); // Прерываем чтение данных из потока.

Теперь все данные собраны и их можно использовать по вашему усмотрению.

Полезные материалы

  1. Использование потоков чтения – Веб-API | MDN — полное руководство по ReadableStreams.
  2. ReadableStream – Веб-API | MDN — детальная информация о ReadableStream.
  3. GitHub – whatwg/streams: Стандартные потоки — ресурс по стандартам потоков.
  4. 2016 — год веб-потоков – JakeArchibald.com — статья Джейка Арчибальда о потоках.
  5. Потоки для немедленной передачи данных | Блог | Chrome для разработчиков — примеры использования потоков от Google.
  6. Потоки: полное руководство | Статьи | web.dev — доступное руководство по потокам.