Home > other >  JS function "Confirm" acting out of order
JS function "Confirm" acting out of order

Time:02-02

The following function mimics a pattern of behavior I would like in my system:

  1. Press button

  2. Change text to an Icon

  3. Ask for user confirmation

  4. Fire Ajax call to an endpoint, and handle the result

  5. Return the text to the previous state.

As it is written, step 3 happens before steps 2 and 4; making step 2 borderline pointless. The Ajax call as I have it in my system loads pretty quickly, but the jQuery function barely blinks the text across. I have made a testable snippet here.

How do I ensure that step 2 correctly in order?

function callAjax() {

      $('#loadingIcon').css('display', 'inline-block');
      $('#buttonText').css('display', 'none');
      if (confirm('Are you sure would you like to proceed?')) {
        $.ajax({
          url: "...",
          timeout: 60000,
          context: document.body,
          success: function (data) {
            location.reload();
          },
          error: function (data) {
            $('#loadingIcon').css('display', 'none');
            $('#buttonText').css('display', 'initial');
          }
        });
      } else {
        $('#loadingIcon').css('display', 'none');
        $('#buttonText').css('display', 'initial');
      }
   }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button onClick=callAjax()>
<span id="buttonText">Loading Text</span>
<span id="loadingIcon" style="display:none;">Icon</span>
</button>

CodePudding user response:

The UI doesn't update until the thread has finished doing what it's doing, and confirm (and prompt, and alert) is a blocking operation.

Ideally you wouldn't use confirm at all. Instead, create a UI within the page to prompt the user for data. It could be form elements on the page, a "modal dialog", etc.

But if you want to use confirm, you'd need to allow the thread to finish first. It's a bit of a hack, but wrapping it in a near-immediate setTimeout should do the trick:

$('#loadingIcon').css('display', 'inline-block');
$('#buttonText').css('display', 'none');
setTimeout(function () {
  if (confirm('Are you sure would you like to proceed?')) {
    $.ajax({
      /* etc. */
    });
  } else {
    $('#loadingIcon').css('display', 'none');
    $('#buttonText').css('display', 'initial');
  }
}, 1); // only delaying 1ms

This introduces a 1ms delay, which would certainly be imperceptible. But by virtue of using setTimeout at all, the thread first finishes everything it's processing (including UI updates) and then executes what's scheduled in the timeout.

  • Related