Промисы в шаблонах

Промисы в шаблонах Petite-Vue

Petite-Vue — это лёгкая и быстрая библиотека для реактивных интерфейсов в JavaScript, которая использует возможности Vue.js, но в более компактном формате. В отличие от более сложного Vue.js, она предназначена для создания простых интерфейсов и динамических элементов без значительных накладных расходов. Одним из важных аспектов работы с интерфейсами в JavaScript является асинхронность, а именно использование промисов, которые играют ключевую роль при взаимодействии с сервером, загрузке данных и других асинхронных операциях. В контексте Petite-Vue промисы могут быть использованы прямо в шаблонах для асинхронной обработки данных и их отображения.

В Petite-Vue промисы могут быть использованы для обработки данных, полученных асинхронным способом. Один из наиболее часто встречающихся случаев — это получение данных с сервера через API. В отличие от классической работы с асинхронными данными в JavaScript, где результаты операции часто обрабатываются с помощью then() или async/await, в Petite-Vue можно использовать реактивность для автоматического обновления интерфейса при получении данных.

Пример использования промиса

Допустим, есть функция, которая загружает данные с сервера и возвращает промис:

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Данные загружены');
    }, 1000);
  });
}

Теперь можно использовать этот промис в шаблоне Petite-Vue. Пример:

<div x-data="{ data: fetchData() }">
  <template x-if="data instanceof Promise">
    <div>Загрузка...</div>
  </template>
  <template x-if="data !== null && !(data instanceof Promise)">
    <div>{{ data }}</div>
  </template>
</div>

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

Работа с асинхронными функциями внутри шаблонов

Petite-Vue позволяет использовать асинхронные функции внутри шаблонов. Вместо того чтобы держать логику получения данных в компоненте или за его пределами, можно инкапсулировать её прямо в атрибуте x-data или в реактивных выражениях.

<div x-data="{ result: null }" x-init="fetchData().then(res => result = res)">
  <template x-if="result === null">
    <div>Загрузка данных...</div>
  </template>
  <template x-if="result !== null">
    <div>{{ result }}</div>
  </template>
</div>

Здесь используется асинхронная функция fetchData(), которая выполняется при инициализации компонента через атрибут x-init. После выполнения промиса результат сохраняется в реактивной переменной result, которая затем отображается в шаблоне. Этот способ позволяет эффективно работать с асинхронными операциями без дополнительной логики вне шаблона.

Обработка ошибок

При работе с промисами важно не забывать о обработке ошибок. В Petite-Vue можно использовать обычные конструкции для обработки ошибок, такие как catch() или обработка через try/catch, если применяется async/await. В шаблоне можно организовать отображение сообщений об ошибках при необходимости.

<div x-data="{ result: null, error: null }" x-init="fetchData().then(res => result = res).catch(err => error = 'Ошибка загрузки')">
  <template x-if="error">
    <div style="color: red;">{{ error }}</div>
  </template>
  <template x-if="result === null && !error">
    <div>Загрузка...</div>
  </template>
  <template x-if="result !== null">
    <div>{{ result }}</div>
  </template>
</div>

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

Использование асинхронных операций в реактивных данных

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

<div x-data="{ data: null, loading: false, fetchData() { this.loading = true; fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(json => { this.data = json; this.loading = false; })
  .catch(() => { this.loading = false; this.data = 'Ошибка'; }) } }">
  <button @click="fetchData()">Загрузить данные</button>
  <template x-if="loading">
    <div>Загрузка...</div>
  </template>
  <template x-if="data !== null">
    <div>{{ data }}</div>
  </template>
</div>

В этом примере при клике на кнопку происходит асинхронная загрузка данных с API. Статус загрузки отображается в виде текста «Загрузка…», пока данные не будут получены, и выводится сам результат, как только операция завершается.

Сложные операции с несколькими промисами

Если требуется работать с несколькими промисами одновременно, можно использовать Promise.all(), чтобы дождаться выполнения всех промисов перед обновлением данных. В Petite-Vue это также может быть реализовано с использованием реактивных данных.

<div x-data="{ results: [], loading: false, fetchData() {
  this.loading = true;
  Promise.all([fetch('https://api.example.com/data1'), fetch('https://api.example.com/data2')])
    .then(responses => Promise.all(responses.map(res => res.json())))
    .then(data => { this.results = data; this.loading = false; })
    .catch(() => { this.loading = false; this.results = ['Ошибка']; }) } }">
  <button @click="fetchData()">Загрузить все данные</button>
  <template x-if="loading">
    <div>Загрузка...</div>
  </template>
  <template x-if="results.length > 0">
    <div>
      <template x-for="result in results" :key="result">
        <div>{{ result }}</div>
      </template>
    </div>
  </template>
</div>

Здесь используется Promise.all(), который ожидает выполнения двух асинхронных запросов, после чего обновляется реактивный массив results. Также предусмотрена обработка ошибок, если один из запросов не удастся.

Заключение

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