Асинхронная валидация

Shepherd.js предоставляет гибкий механизм создания интерактивных руководств (tours) для веб-приложений. Одной из важных возможностей является асинхронная валидация шагов, которая позволяет управлять переходом между шагами на основе динамических условий.

Основы асинхронной валидации

Каждый шаг Shepherd.js может содержать обработчики событий, включая beforeShowPromise и beforeNext. Эти обработчики позволяют выполнять асинхронные операции, прежде чем шаг будет показан или завершён:

const tour = new Shepherd.Tour({
  defaultStepOptions: {
    scrollTo: true
  }
});

tour.addStep({
  id: 'step-1',
  text: 'Введите своё имя',
  attachTo: { element: '#name-input', on: 'bottom' },
  buttons: [
    {
      text: 'Далее',
      action: tour.next
    }
  ],
  beforeShowPromise: () => {
    return new Promise((resolve, reject) => {
      const input = document.querySelector('#name-input');
      if (input.value.trim() !== '') {
        resolve();
      } else {
        alert('Поле не может быть пустым');
        reject();
      }
    });
  }
});

В примере выше beforeShowPromise проверяет содержимое поля ввода и блокирует показ шага до выполнения условия. Промис может быть отклонён, что предотвратит отображение шага и позволит пользователю исправить ошибку.

Использование beforeNext для динамической проверки

beforeNext вызывается перед переходом к следующему шагу. Этот метод идеально подходит для валидации данных, введённых пользователем, перед продолжением тура:

tour.addStep({
  id: 'step-2',
  text: 'Введите корректный email',
  attachTo: { element: '#email-input', on: 'right' },
  buttons: [
    {
      text: 'Далее',
      action: tour.next
    }
  ],
  beforeNext: () => {
    return new Promise((resolve, reject) => {
      const email = document.querySelector('#email-input').value;
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (emailRegex.test(email)) {
        resolve();
      } else {
        alert('Введите корректный email');
        reject();
      }
    });
  }
});

Ключевой момент: использование промисов позволяет не блокировать основной поток JavaScript и корректно обрабатывать асинхронные операции, такие как сетевые запросы или таймеры.

Асинхронные запросы на сервер

Иногда необходимо проверять данные не локально, а отправляя их на сервер для проверки. В таких случаях beforeNext можно комбинировать с fetch или любым другим API-запросом:

tour.addStep({
  id: 'step-3',
  text: 'Проверка доступности имени пользователя',
  attachTo: { element: '#username-input', on: 'top' },
  buttons: [
    {
      text: 'Далее',
      action: tour.next
    }
  ],
  beforeNext: () => {
    const username = document.querySelector('#username-input').value;
    return fetch(`/api/check-username?username=${username}`)
      .then(response => response.json())
      .then(data => {
        if (data.available) {
          return Promise.resolve();
        } else {
          alert('Имя пользователя занято');
          return Promise.reject();
        }
      });
  }
});

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

Обработка ошибок и пользовательский опыт

Для улучшения взаимодействия важно корректно обрабатывать отклонённые промисы:

  • Использовать визуальные подсказки (tooltip, alert, модальное окно)
  • Не блокировать весь интерфейс, оставляя возможность исправить ошибку
  • Добавлять задержку или индикатор загрузки при длительных асинхронных операциях
beforeNext: () => {
  const loader = document.querySelector('#loader');
  loader.style.display = 'block';
  return fetch('/api/validate')
    .then(res => res.json())
    .finally(() => {
      loader.style.display = 'none';
    })
    .then(data => {
      if (data.valid) {
        return Promise.resolve();
      } else {
        return Promise.reject();
      }
    });
}

Резюме ключевых практик

  • Использовать beforeShowPromise для проверки условий перед показом шага.
  • Применять beforeNext для асинхронной валидации перед переходом к следующему шагу.
  • Обрабатывать отклонённые промисы с уведомлением пользователя.
  • Интегрировать серверные проверки для динамических данных.
  • Добавлять индикаторы загрузки при долгих запросах для улучшения UX.

Асинхронная валидация в Shepherd.js превращает стандартные туры в интерактивные, динамичные и безопасные руководства, способные реагировать на действия пользователя и данные приложения в реальном времени.