AIO SDK Form: Submit Promises и Before Submit Promises

Назначение

AIO SDK Form предоставляет два механизма для асинхронной пользовательской логики вокруг отправки формы:

  • beforeSubmitPromises - выполняются до начала реальной отправки формы
  • submitPromises - выполняются во время отправки и могут отслеживать результат реальной отправки через formPromise

Оба принимают массив функций, и каждая функция должна возвращать Promise.

Что такое Promise в JavaScript

Promise это объект, который представляет результат асинхронной операции.

У Promise три состояния:

  • pending - операция ещё выполняется
  • fulfilled - операция завершилась успешно
  • rejected - операция завершилась с ошибкой

Базовый пример

const promise = new Promise((resolve, reject) => {
  const ok = true;

  if (ok) {
    resolve("success");
  } else {
    reject("error");
  }
});

Обработка результата

promise
  .then((result) => {
    console.log("Success:", result);
  })
  .catch((reason) => {
    console.log("Error:", reason);
  })
  .finally(() => {
    console.log("This block always runs");
  });

Что делают resolve и reject

  • resolve(value) - завершает Promise успешно
  • reject(reason) - завершает Promise с ошибкой

Как Promise используются в AIO SDK Form

Форма использует Promise в двух местах:

beforeSubmitPromises

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

Примеры:

  • подтверждение / модальное окно перед отправкой
  • дополнительная валидация
  • обязательное действие пользователя перед отправкой
  • trigger перед fetch

submitPromises

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

Примеры:

  • модальное окно ожидания
  • собственный UI для успеха / ошибки
  • смена текста модального окна, пока запрос выполняется
  • собственный редирект после ответа сервера

Сигнатуры колбэков

beforeSubmitPromises

(ut, aioExchange, config) => Promise

Аргументы

  • ut - UTILS
  • aioExchange - объект exchange, можно использовать для trigger
  • config - текущая конфигурация формы

submitPromises

(ut, formPromise, aioExchange, config) => Promise

Аргументы

  • ut - UTILS
  • formPromise - Promise результата реальной отправки формы
  • aioExchange - объект exchange
  • config - текущая конфигурация формы

Как работают beforeSubmitPromises

Общая логика

При отправке формы SDK:

  1. собирает данные формы
  2. проверяет номер телефона
  3. блокирует форму
  4. запускает все beforeSubmitPromises
  5. ждёт, пока все они завершатся успешно
  6. только после этого запускает реальный fetch

Что означает resolve()

Если колбэк внутри beforeSubmitPromises вызывает resolve(), это означает:

  • этот шаг завершился успешно
  • форма может продолжить процесс отправки

Что означает reject()

Если колбэк внутри beforeSubmitPromises вызывает reject(), это означает:

  • отправка остановлена
  • реальный fetch не запускается
  • ошибка показывается через submitErrorCb

Важный вывод

beforeSubmitPromises это блокирующий этап перед отправкой.

Как работают submitPromises

Общая логика

После успешного завершения beforeSubmitPromises SDK:

  1. создаёт внутренний formPromise
  2. запускает все submitPromises
  3. сразу же запускает реальный fetch

Что такое formPromise

formPromise представляет результат реальной отправки формы.

При успешной отправке:

formPromise.then((response) => {
  // response = { success: true, url: "..." }
});

При неудачной отправке:

formPromise.catch((reason) => {
  // reason = rejectedMessage
});

Что означает resolve() внутри submitPromises

resolve() завершает только тот Promise, который вернул ваш собственный колбэк.

Он не:

  • запускает отправку
  • отменяет отправку
  • управляет fetch
  • управляет submitErrorCb

Что означает reject() внутри submitPromises

reject() отклоняет только ваш собственный Promise.

Он не:

  • отменяет реальную отправку формы
  • останавливает fetch
  • автоматически запускает обработку ошибки формы

Важный вывод

submitPromises это неблокирующая обёртка вокруг отправки: она может отслеживать formPromise, но не управляет тем, будет ли форма отправлена на самом деле.

Порядок отправки формы

Полный порядок отправки такой:

  1. пользователь нажимает кнопку отправки
  2. SDK вызывает preventDefault()
  3. SDK собирает данные формы
  4. SDK проверяет номер телефона
  5. SDK вызывает disableForms()
  6. SDK запускает beforeSubmitPromises
  7. если все beforeSubmitPromises завершились через resolve():
    • создаётся внутренний formPromise
    • запускаются submitPromises
    • запускается реальный fetch
  8. если сервер возвращает success: true:
    • formPromise разрешается
    • вызывается successForms(...)
    • затем вызывается successFn(url)
  9. если сервер возвращает ошибку, невалидный JSON или success: false:
    • formPromise отклоняется с rejectedMessage
    • вызывается submitErrorCb

Когда использовать beforeSubmitPromises

Используйте beforeSubmitPromises, когда нужно:

  • разрешить или заблокировать отправку
  • показать подтверждение перед отправкой
  • дождаться обязательного действия пользователя
  • выполнить обязательную логику до отправки формы

Пример: подтверждение отправки

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      beforeSubmitPromises: [
        (ut, aioExchange, config) => new Promise((resolve, reject) => {
          if (confirm("Submit the form?")) {
            resolve();
          } else {
            reject();
          }
        })
      ]
    }
  }
});
</script>

Пример: trigger перед отправкой

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      beforeSubmitPromises: [
        (ut, aioExchange, config) => new Promise((resolve, reject) => {
          aioExchange.trigger("ad_name", "FORM YES");
          resolve();
        })
      ]
    }
  }
});
</script>

Пример: модальное окно перед отправкой

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      beforeSubmitPromises: [
        (ut, aioExchange, config) => new Promise((resolve, reject) => {
          const modal = document.getElementById("before-promise-modal");

          ut.openModal({
            nativeElement: modal,
            resolve: resolve,
            reject: reject,
            countDown: 5,
            countDownStyle: "minutes",
            countDownCb: () => {
              ut.closeModal(modal);
              resolve();
            }
          });
        })
      ]
    }
  }
});
</script>

Когда использовать submitPromises

Используйте submitPromises, когда нужно:

  • показать UI ожидания во время отправки
  • обработать результат успеха / ошибки через formPromise
  • обновить содержимое модального окна после ответа сервера
  • построить собственный сценарий успеха или ошибки

Пример: простое модальное окно ожидания

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      successFn: (url) => null,
      submitPromises: [
        (ut, formPromise, aioExchange, config) => new Promise((resolve, reject) => {
          const modal = document.getElementById("submit-modal");

          formPromise
            .then((response) => {
              modal.querySelector("h1").innerText = "Success: " + response.url;
            })
            .catch((reason) => {
              modal.querySelector("h1").innerText = "Failed: " + reason;
            });

          ut.openModal({
            nativeElement: modal,
            countDown: 3,
            countDownStyle: "minutes",
            countDownCb: () => {
              resolve();
            }
          });
        })
      ]
    }
  }
});
</script>

Пример: модальное окно успеха / ошибки

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      successFn: (url) => null,
      submitPromises: [
        (ut, formPromise, aioExchange, config) => new Promise((resolve, reject) => {
          const waitingModal = document.getElementById("submit-promise-modal");
          const successModal = document.getElementById("submit-success-modal");
          const failedModal = document.getElementById("submit-failed-modal");

          formPromise
            .then((response) => {
              ut.closeModal(waitingModal);
              ut.openModal({ nativeElement: successModal });
            })
            .catch((reason) => {
              ut.closeModal(waitingModal);
              ut.openModal({ nativeElement: failedModal });
            });

          ut.openModal({
            nativeElement: waitingModal,
            countDown: 10,
            countDownStyle: "minutes",
            countDownCb: () => {
              resolve();
            }
          });
        })
      ]
    }
  }
});
</script>

Пример: собственный редирект после успеха

<script>
window.aioBus = window.aioBus || [];

window.aioBus.push({
  type: "config",
  config: {
    form: {
      successFn: (url) => null,
      submitPromises: [
        (ut, formPromise, aioExchange, config) => new Promise((resolve, reject) => {
          formPromise
            .then((response) => {
              setTimeout(() => {
                window.location.href = response.url;
              }, 2000);
            })
            .catch((reason) => {
              console.log("Submit failed:", reason);
            });

          resolve();
        })
      ]
    }
  }
});
</script>

Разница между beforeSubmitPromises и submitPromises

ПараметрbeforeSubmitPromisessubmitPromises
Когда выполняетсяДо реальной отправкиВо время отправки
Блокирует отправку формыДаНет
Может остановить fetchДаНет
Получает formPromiseНетДа
Подходит для подтверждения / предварительной проверкиДаНет
Подходит для UI отправкиОграниченноДа

Поведение нескольких Promise

И beforeSubmitPromises, и submitPromises обрабатываются через Promise.all(...).

Это означает:

  • все Promise в массиве запускаются параллельно
  • это не последовательная цепочка

Пример

beforeSubmitPromises: [
  promise1,
  promise2,
  promise3
]

Все три колбэка запустятся одновременно.

Если нужна последовательная логика

Если шаги должны выполняться строго один за другим, лучше объединить их в один Promise.

beforeSubmitPromises: [
  (ut, aioExchange, config) => new Promise(async (resolve, reject) => {
    try {
      await step1();
      await step2();
      await step3();
      resolve();
    } catch (e) {
      reject(e);
    }
  })
]

Работа с successFn

После успешной отправки SDK вызывает successFn(json.url).

По умолчанию:

successFn: (url) => window.top.location.replace(url)

Если нужен собственный сценарий успеха, обычно его переопределяют так:

successFn: (url) => null

После этого логику редиректа можно обрабатывать вручную внутри submitPromises.


Шаблоны для повторного использования

Шаблон beforeSubmitPromises

beforeSubmitPromises: [
  (ut, aioExchange, config) => new Promise((resolve, reject) => {
    try {
      // Logic before submit
      resolve();
    } catch (e) {
      reject(e);
    }
  })
]

Шаблон submitPromises

submitPromises: [
  (ut, formPromise, aioExchange, config) => new Promise((resolve, reject) => {
    try {
      formPromise
        .then((response) => {
          // success
        })
        .catch((reason) => {
          // failed
        });

      resolve();
    } catch (e) {
      reject(e);
    }
  })
]

Итоги

beforeSubmitPromises

Используются для обязательной логики до отправки формы.

  • блокируют отправку
  • resolve() разрешает отправку
  • reject() останавливает отправку

submitPromises

Используются для логики вокруг отправки формы.

  • не блокируют отправку
  • получают formPromise
  • подходят для собственного UI и собственных сценариев успеха / ошибки

formPromise

Это Promise результата реальной отправки формы.

  • then(response) -> успешная отправка
  • catch(reason) -> неудачная отправка

Связаться с поддержкой

Telegram