Интеграция с Fetch API и XMLHttpRequest

Riot.js предоставляет минималистичный и эффективный способ создания компонентов, которые динамически обновляют интерфейс. Для работы с внешними данными, получаемыми по сети, часто используют Fetch API или XMLHttpRequest (XHR). Разберем интеграцию этих инструментов в компоненты Riot.js.


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

Fetch API является современным способом выполнения HTTP-запросов и возвращает Promise, что упрощает работу с асинхронными операциями.

Пример асинхронного запроса

<user-list>
  <ul>
    <li each={user in users}>{user.name}</li>
  </ul>

  <script>
    export default {
      users: [],

      onMounted() {
        fetch('https://jsonplaceholder.typicode.com/users')
          .then(response => {
            if (!response.ok) throw new Error('Ошибка сети');
            return response.json();
          })
          .then(data => {
            this.users = data;
            this.update();
          })
          .catch(error => console.error(error));
      }
    }
  </script>
</user-list>

Ключевые моменты:

  • fetch() возвращает Promise, который разрешается объектом Response.
  • Метод .json() также возвращает Promise.
  • Для обновления интерфейса после получения данных используется this.update().

Использование async/await

Riot.js поддерживает использование async/await для более читаемого кода:

onMounted: async function() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) throw new Error('Ошибка сети');
    this.users = await response.json();
    this.update();
  } catch (error) {
    console.error(error);
  }
}

Работа с XMLHttpRequest

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

Пример XHR в компоненте

<post-list>
  <ul>
    <li each={post in posts}>{post.title}</li>
  </ul>

  <script>
    export default {
      posts: [],

      onMounted() {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts', true);

        xhr.onreadystatecha nge = () => {
          if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              this.posts = JSON.parse(xhr.responseText);
              this.update();
            } else {
              console.error('Ошибка XHR', xhr.statusText);
            }
          }
        };

        xhr.send();
      }
    }
  </script>
</post-list>

Особенности XHR:

  • readyState отслеживает стадии запроса.
  • Обработчик onreadystatechange вызывается при каждом изменении состояния.
  • Преобразование ответа в JSON выполняется через JSON.parse.

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

В Riot.js реактивность компонентов достигается через обновление состояния с помощью this.update(). Любые изменения данных после получения ответа от Fetch или XHR должны сопровождаться вызовом update(), чтобы интерфейс отразил новые значения.

Пример динамического обновления при событии

<todo-app>
  <input type="text" ref="taskInput">
  <button oncl ick={addTask}>Добавить задачу</button>

  <ul>
    <li each={task in tasks}>{task}</li>
  </ul>

  <script>
    export default {
      tasks: [],

      addTask() {
        const value = this.$refs.taskInput.value;
        if (!value) return;

        fetch('/api/addTask', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ task: value })
        })
        .then(res => res.json())
        .then(data => {
          this.tasks.push(data.task);
          this.update();
          this.$refs.taskInput.value = '';
        })
        .catch(err => console.error(err));
      }
    }
  </script>
</todo-app>

Обработка ошибок и статус-кодов

При интеграции с внешними API важно учитывать:

  • Проверку статуса ответа (response.ok или xhr.status).
  • Обработку ошибок сети (catch или проверка xhr.statusText).
  • Возможность повторных запросов или тайм-аутов при необходимости.

Пример обработки тайм-аута в XHR:

xhr.timeout = 5000; // 5 секунд
xhr.ontime out = () => console.error('Запрос превысил время ожидания');

Параллельные запросы

Fetch API позволяет выполнять несколько запросов одновременно через Promise.all:

onMounted: async function() {
  try {
    const [users, posts] = await Promise.all([
      fetch('https://jsonplaceholder.typicode.com/users').then(r => r.json()),
      fetch('https://jsonplaceholder.typicode.com/posts').then(r => r.json())
    ]);
    
    this.users = users;
    this.posts = posts;
    this.update();
  } catch (error) {
    console.error(error);
  }
}

Интеграция с жизненным циклом компонента

  • onBeforeMount: Можно инициировать подготовительные действия до монтирования.
  • onMounted: Оптимальное место для сетевых запросов, так как DOM уже доступен.
  • onUnmounted: Можно отменить асинхронные операции или очистить таймеры, чтобы предотвратить утечки памяти.

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