Web Streams API

Web Streams API предоставляет мощный механизм работы с потоками данных в браузере, позволяя обрабатывать большие объёмы информации асинхронно и эффективно. В сочетании с Vue.js API это открывает возможности для динамического обновления интерфейса при поступлении данных, минимизируя задержки и нагрузку на память.

Потоки и их виды

В Streams API существует три ключевых типа потоков:

  • ReadableStream – поток для чтения данных. Используется, когда необходимо получать данные постепенно, например, при загрузке больших файлов или потоковом API.
  • WritableStream – поток для записи данных. Применяется для отправки данных на сервер или генерации динамического контента.
  • TransformStream – поток для преобразования данных между чтением и записью, позволяет применять фильтры, преобразования формата и другие операции по ходу передачи.

Каждый поток работает асинхронно и поддерживает интерфейсы getReader() и getWriter(), обеспечивая удобный контроль над процессом передачи данных.

Работа с ReadableStream

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

const readableStream = new ReadableStream({
  start(controller) {
    controller.enqueue('Привет, ');
    controller.enqueue('мир!');
    controller.close();
  }
});

const reader = readableStream.getReader();

async function readStream() {
  let result = '';
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    result += value;
  }
  console.log(result); // Привет, мир!
}

readStream();

В этом примере controller.enqueue() добавляет данные в поток, а reader.read() асинхронно извлекает их. Такой подход позволяет обрабатывать данные по частям, что особенно полезно для больших файлов или потокового контента.

Использование потоков с Vue.js

Vue.js обеспечивает реактивность интерфейса, что делает Streams API особенно удобным для динамических приложений. Например, можно обновлять состояние компонента по мере поступления данных:

<template>
  <div>
    <p v-for="chunk in chunks" :key="chunk.id">{{ chunk.text }}</p>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const chunks = ref([]);

    async function fetchStream() {
      const response = await fetch('/api/stream');
      const reader = response.body.getReader();
      let id = 0;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const text = new TextDecoder().decode(value);
        chunks.value.push({ id: id++, text });
      }
    }

    fetchStream();

    return { chunks };
  }
};
</script>

Здесь поток данных с сервера декодируется в текст и добавляется в реактивный массив Vue, автоматически обновляя DOM при каждом новом фрагменте.

TransformStream для обработки данных на лету

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

const upperCaseTransform = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(chunk.toUpperCase());
  }
});

const readable = new ReadableStream({
  start(controller) {
    controller.enqueue('vue.js streams api');
    controller.close();
  }
});

const transformed = readable.pipeThrough(upperCaseTransform);
const reader = transformed.getReader();

(async () => {
  const { value } = await reader.read();
  console.log(value); // VUE.JS STREAMS API
})();

Комбинация pipeThrough() и реактивных данных Vue позволяет создавать интерфейсы, где контент обрабатывается и отображается мгновенно, без ожидания полной загрузки.

Интеграция с fetch и потоковыми API

Streams API тесно интегрирован с fetch(). Ответ от сервера можно читать по частям, что улучшает пользовательский опыт при работе с большими JSON или бинарными данными:

async function fetchLargeData() {
  const response = await fetch('/api/large-data');
  const reader = response.body.getReader();
  let receivedLength = 0;
  const chunks = [];

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    chunks.push(value);
    receivedLength += value.length;
  }

  const fullData = new TextDecoder().decode(new Uint8Array(chunks.flat()));
  console.log(fullData);
}

fetchLargeData();

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

Советы по оптимизации

  • Использовать TextDecoder и Uint8Array для минимизации затрат на преобразование данных.
  • Применять TransformStream для фильтрации, сжатия или шифрования на лету.
  • Интегрировать потоковые данные с реактивными структурами Vue (ref, reactive) для автоматического обновления интерфейса.
  • Для больших массивов данных применять virtual scrolling, чтобы DOM не перегружался.

Web Streams API в связке с Vue.js создаёт эффективный механизм для работы с потоковыми данными, позволяя строить высокопроизводительные приложения с интерактивным интерфейсом и минимальной задержкой.