AIO SDK Form: Submit Promises and Before Submit Promises

Purpose

AIO SDK Form provides two mechanisms for asynchronous custom logic around form submission:

  • beforeSubmitPromises - executed before the real form submission starts
  • submitPromises - executed during the submission process and can observe the real submission result through formPromise

Both accept an array of functions, and each function must return a Promise.

What is a Promise in JavaScript

A Promise is an object that represents the result of an asynchronous operation.

A Promise has 3 states:

  • pending - the operation is still running
  • fulfilled - the operation completed successfully
  • rejected - the operation failed

Basic example

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

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

Handling the result

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

What resolve and reject do

  • resolve(value) - completes the Promise successfully
  • reject(reason) - completes the Promise with an error

How Promises are used in AIO SDK Form

The form uses Promises in two places:

beforeSubmitPromises

Used for logic that must finish before the form is actually submitted.

Examples:

  • confirm / modal before submit
  • extra validation
  • required user action before submission
  • trigger before fetch

submitPromises

Used for logic that should run around an already started submit.

Examples:

  • waiting modal
  • custom success / failed UI
  • changing modal text while request is in progress
  • custom redirect after the server response

Callback signatures

beforeSubmitPromises

(ut, aioExchange, config) => Promise

Arguments

  • ut - UTILS
  • aioExchange - exchange object, can be used for trigger
  • config - current form config

submitPromises

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

Arguments

  • ut - UTILS
  • formPromise - Promise of the real form submission result
  • aioExchange - exchange object
  • config - current form config

How beforeSubmitPromises work

General logic

When the form is submitted, the SDK:

  1. collects form data
  2. validates the phone number
  3. disables the form
  4. runs all beforeSubmitPromises
  5. waits until all of them finish successfully
  6. only then starts the real fetch

What resolve() means

If a callback inside beforeSubmitPromises calls resolve(), it means:

  • this step completed successfully
  • the form may continue the submit process

What reject() means

If a callback inside beforeSubmitPromises calls reject(), it means:

  • submit is stopped
  • the real fetch is not started
  • an error is shown through submitErrorCb

Important result

beforeSubmitPromises is a blocking pre-submit stage.

How submitPromises work

General logic

After beforeSubmitPromises finish successfully, the SDK:

  1. creates an internal formPromise
  2. starts all submitPromises
  3. immediately starts the real fetch

What formPromise is

formPromise represents the result of the real form submission.

On successful submission:

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

On failed submission:

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

What resolve() means inside submitPromises

resolve() only completes the Promise returned by your own callback.

It does not:

  • start submit
  • cancel submit
  • control fetch
  • control submitErrorCb

What reject() means inside submitPromises

reject() only rejects your custom Promise.

It does not:

  • cancel the real form submission
  • stop fetch
  • automatically trigger the form error flow

Important result

submitPromises is a non-blocking wrapper around submit, which can observe formPromise, but does not control whether the form is actually sent.

Form submission flow

The full submit flow is:

  1. user clicks submit
  2. SDK calls preventDefault()
  3. SDK collects form data
  4. SDK validates the phone number
  5. SDK calls disableForms()
  6. SDK runs beforeSubmitPromises
  7. if all beforeSubmitPromises finish with resolve():
    • internal formPromise is created
    • submitPromises are started
    • real fetch is started
  8. if the server returns success: true:
    • formPromise is resolved
    • successForms(...) is called
    • then successFn(url) is called
  9. if the server returns an error, invalid JSON, or success: false:
    • formPromise is rejected with rejectedMessage
    • submitErrorCb is called

When to use beforeSubmitPromises

Use beforeSubmitPromises when you need to:

  • allow or block submit
  • show confirmation before submission
  • wait for required user action
  • run required logic before the form is sent

Example: submit confirmation

<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>

Example: trigger before submit

<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>

Example: modal before submit

<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>

When to use submitPromises

Use submitPromises when you need to:

  • show waiting UI during submission
  • handle success / failed result through formPromise
  • update modal content after the server response
  • build a custom success or error flow

Example: simple waiting modal

<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>

Example: success / failed modal

<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>

Example: custom redirect after success

<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>

Difference between beforeSubmitPromises and submitPromises

ParameterbeforeSubmitPromisessubmitPromises
When it runsBefore real submitDuring submit
Blocks form submissionYesNo
Can stop fetchYesNo
Receives formPromiseNoYes
Suitable for confirm / pre-checkYesNo
Suitable for submit UILimitedYes

Behavior of Multiple Promises

Both beforeSubmitPromises and submitPromises are handled through Promise.all(...).

This means:

  • all Promises in the array are started in parallel
  • this is not a sequential chain

Example

beforeSubmitPromises: [
  promise1,
  promise2,
  promise3
]

All three callbacks will start at the same time.

If sequential logic is required

If steps must run strictly one after another, it is better to combine them into a single Promise.

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

Working with successFn

After a successful submission, the SDK calls successFn(json.url).

By default:

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

If a custom success flow is needed, it is common to override it with:

successFn: (url) => null

After that, redirect logic can be handled manually inside submitPromises.


Reusable templates

beforeSubmitPromises template

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

submitPromises template

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

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

Summary

beforeSubmitPromises

Used for required logic before the form is sent.

  • blocks submit
  • resolve() allows submission
  • reject() stops submission

submitPromises

Used for logic around form submission.

  • does not block submit
  • receives formPromise
  • useful for custom UI and custom success / error flows

formPromise

This is the Promise of the real form submission result.

  • then(response) -> successful submit
  • catch(reason) -> failed submit

Contact Our Support

Telegram