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

Асинхронная валидация в Quasar — это механизм проверки данных формы, который позволяет обрабатывать условия, требующие обращения к внешним источникам, API или длительных вычислений, до того как форма будет отправлена. В отличие от синхронной валидации, которая выполняется мгновенно на основе локальных правил, асинхронная может включать задержки и возвращать результат только после завершения всех операций.

Основные принципы

  1. Возврат промисов Асинхронная валидация всегда работает с промисами. Любое правило, которое может потребовать асинхронного запроса, должно возвращать Promise, который резолвится в true при успешной проверке или в строку с текстом ошибки при неудаче.

  2. Совместимость с v-model и rules Quasar использует свойства rules для компонентов ввода, таких как q-input или q-select. Каждое правило может быть функцией, которая возвращает либо булево значение, либо промис. Это позволяет без изменений использовать как синхронные, так и асинхронные проверки.

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

const checkUsernameAvailability = (username) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      const unavailable = ['admin', 'root', 'test'];
      if (unavailable.includes(username)) {
        resolve('Имя пользователя уже занято');
      } else {
        resolve(true);
      }
    }, 1000);
  });
};

const usernameRules = [
  value => !!value || 'Поле обязательно для заполнения',
  value => checkUsernameAvailability(value)
];

В этом примере первое правило проверяет, что поле не пустое, а второе — делает асинхронный запрос (имитация через setTimeout) для проверки доступности имени пользователя.

Интеграция с q-form

Компонент q-form позволяет централизованно управлять валидацией всех полей формы, включая асинхронные. Для этого используется метод validate(), который возвращает промис:

<q-form ref="form" @submit.prevent="submitForm">
  <q-input v-model="username" :rules="usernameRules" label="Имя пользователя" />
  <q-btn type="submit" label="Отправить" />
</q-form>

<script>
export default {
  data() {
    return {
      username: ''
    }
  },
  methods: {
    async submitForm() {
      const isValid = await this.$refs.form.validate();
      if (isValid) {
        console.log('Форма прошла проверку');
      } else {
        console.log('Форма содержит ошибки');
      }
    }
  }
}
</script>

Метод validate() корректно обрабатывает промисы из правил и ожидает их завершения, обеспечивая синхронизацию проверки перед отправкой данных.

Обработка нескольких асинхронных правил

Если одно поле содержит несколько асинхронных правил, они выполняются последовательно. Quasar агрегирует результаты и останавливает проверку при первом обнаруженном несоответствии. При необходимости можно реализовать параллельную проверку, используя Promise.all внутри собственного правила:

const asyncRules = [
  async value => {
    const results = await Promise.all([
      checkUsernameAvailability(value),
      checkUsernameFormat(value)
    ]);
    const error = results.find(r => r !== true);
    return error || true;
  }
];

Это позволяет одновременно проверять несколько условий и возвращать первую ошибку, если она есть.

Учет состояния загрузки

Для улучшения UX можно отслеживать состояние асинхронной проверки, например через loading:

data() {
  return {
    username: '',
    isChecking: false
  };
},
methods: {
  async checkUsername(value) {
    this.isChecking = true;
    const result = await checkUsernameAvailability(value);
    this.isChecking = false;
    return result;
  }
},
computed: {
  usernameRules() {
    return [
      value => !!value || 'Поле обязательно',
      value => this.checkUsername(value)
    ];
  }
}

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

Асинхронная валидация и динамические формы

В динамических формах, где поля добавляются или удаляются на лету, асинхронные правила интегрируются без изменений. Главное — корректно обновлять массив правил и привязку к v-model. Например, при добавлении нового поля:

this.dynamicFields.push({
  model: '',
  rules: [
    v => !!v || 'Обязательное поле',
    v => checkSomeAPI(v)
  ]
});

Методы validate() и resetValidation() применимы к динамическим полям точно так же, как к статическим.

Рекомендации по производительности

  • Минимизировать количество асинхронных вызовов при каждом вводе. Можно использовать debounce или проверять изменения только при blur.
  • Использовать кэширование результатов проверок, если одно и то же значение проверяется несколько раз.
  • Обрабатывать ошибки сетевых запросов внутри правил, возвращая понятное сообщение вместо исключения.

Асинхронная валидация в Quasar обеспечивает гибкий, безопасный и удобный способ проверки данных, когда синхронные правила недостаточны. Она органично сочетается с реактивностью Vue и встроенными механизмами форм.