The asynchronous AJAX request is finished after the function call has been made. This can be achieved without using

I am in search of a solution that will allow an AJAX API call to finish before the containing function does without relying on jQuery as a dependency for just one REST call...

After going through multiple solutions, all of which involve using jQuery, I came across this question How do I return the response from an asynchronous call?. However, I am determined to find a way to achieve this without adding jQuery as a dependency.

Currently, when a failing zip code value is inputted and the user clicks Submit, an alert pops up displaying other failed business rules but not the error related to "Mismatch in State and Zip."). Upon console logging, it seems that the REST call is successfully made and a response is received, but the alert(error) gets triggered before the async REST call completes and appends the value of error.

JS

function checkForm(form){
  var state = form.state;
  var zip = form.zip;
  var error = '';
  var flag = 0;

  var ckZip = checkZip(state, zip);
  if (ckZip.flag == 1){
    flag = 1;
  }
  error += ckZip.error;

  // show error and disable form submit if flag == 1
  if (flag == 1){
    alert(error);
    return false;
  }
}

function checkZip(state, zip){
  var state = form.state;
  var zip = form.zip;
  var error = '';
  var flag = 0;

  // check if value entered
  if (zip == ''){
    error += "Please provide a zip/postal code.\r\n";
    flag = 1;
  }

  // business rule: cannot enter - in a ZIP
  if (zip.search(/\x2d/) != -1){
    error += "Please remove dash from zip or postal code.\r\n";
    flag = 1;
  }

  // check if state and zip match
  // IMPORTANT: Fill in your client key
  var clientKey = "this-is-a-valid-key";
  var zipcode = zip.substring(0, 5);
  var url = "https://www.zipcodeapi.com/rest/"+clientKey+"/info.json/" + zipcode + "/radians";
  // Make AJAX request
  var request = new XMLHttpRequest();
  request.open('GET', url, true);

  request.onreadystatechange = function() {
    if (this.readyState === 4) {
      if (this.status >= 200 && this.status < 400) {alert("Got it");
        // Success!
        var data = JSON.parse(this.responseText);alert(data.state);
        if (data.state != state){
          error += "Mismatch in State and Zip.\r\n";
      flag = 1;
        }
      } else {
        // Error :(
        var response = JSON.parse(this.responseText);
        error += "error: " + response.error_msg;
      }
    }
  };

  request.send();
  request = null;

  return {flag: flag, error: error};
}

HTML

<form>
  <select id="state" name="state">
      <option value="" selected=""></option>
      <option value="AA">APO AA</option>                
      <option value="AE">APO AE</option>                
      <option value="AP">APO AP</option>                
      <option value="AL">Alabama</option>               
      <option value="AK">Alaska</option>                
      <option value="AZ">Arizona</option>               
      <option value="AR">Arkansas</option>                
      <option value="CA">California</option>                
      <option value="CO">Colorado</option>                
      <option value="CT">Connecticut</option> 
      <!-- ... -->              
  </select>

  <input type="text" id="zip" name="zip" value="">   
  <input type="Submit" id="Submit" name="Submit" value="Continue" onclick="return checkForm(this.form)">
</form>

Answer №1

To actually retrieve information from the ajax call within your function, you may consider making the ajax call synchronous. However, I advise against this approach as it can freeze the UI of the browser tab, leading to a negative user experience. In addition, it is not necessary.

Instead, opt for an asynchronous call and learn how to handle the inability of the function to return information directly as a return value. You can refer to this question and its answers for guidance on how to achieve this. It's simpler than one might think. :-)

If you want to make your checkZip function work asynchronously, follow these steps:

Firstly, move the ajax call from the submit button to the form itself:

<form onsubmit="return checkZip(this)">

Next, ensure that checkZip always prevents form submission by returning false, and then submit the form once the ajax call is completed:

function checkZip(form) {

    // ...

    request.onreadystatechange = function() {
        // ...
        if (/* it's okay to submit the form*/) {
            form.submit(); // Does NOT call the handler again
        } else {
            // show error to user
        }
    };

    // Prevent initial form submission
    return false;
}

Keep in mind that since the form was not actually submitted when the "Submit" button was pressed, it will not include the Submit field with the value

Continue</code. If needed, you can remove the <code>name
from the submit button and add a hidden field instead:

<input type="hidden" name="Submit" value="Continue">

While it is technically feasible to make the ajax call synchronous by setting the third argument of open to false, I strongly discourage doing so.

request.open('GET', url, false);
// ----------------------^^^^^

Once again, I highly recommend avoiding synchronous ajax calls.

Answer №2

To ensure synchronous behavior, you have the option to use the XMLHTTPRequest object in a synchronous mode:

var request = new XMLHttpRequest();
request.open('GET', url, false);

It is worth noting that this method is generally discouraged by many developers.

Alternatively, you could place your alert function inside a setTimeout with a short delay to give the request enough time to complete processing:

setTimeout(function() {
    // Display error message and prevent form submission if flag is equal to 1
    if (flag == 1) {
        alert(error);
        return false;
    }
}, 1000);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with toggleClass not functioning properly after receiving data from an AJAX call

On my website, I have a link that triggers an AJAX request. However, when the response comes back and I try to use the toggleClass function in the following .js code snippet, it doesn't work as expected: $(document).ready(function(){ $("td").click( ...

Which method is more appropriate for my request - GET or POST? Or should I consider

Recently, I've been exploring the world of get and post methods and could use some guidance! Within my App.js file, there is a user text input field and a submit button. I have a couple of tasks in mind for handling this information: Retrieve a str ...

There seems to be a hitch in the functioning of the JavaScript codes

I'm having trouble calculating the amount using jQuery. Could someone please review my code and let me know what's wrong? Here are my Javascript and jQuery codes: After making changes: $(document).ready(function() { $('.home_banner&ap ...

Issue with displaying response content within a div using Ajax

I am encountering an issue when trying to display the value of an AJAX response inside a div. The problem occurs after I receive the response, as it shows in the div for just a split second before automatically hiding. Even after changing the ID to a class ...

Ways to modify menu when button is clicked?

I am currently working on creating an authentication-based menu in a React app. Menu Data: const menuItems = { primaryMenus: [ { title: 'Messages' }, { title: 'Register' }, { subMenus: { title: ...

Currently, I am utilizing Angular 2 to extract the name of a restaurant from a drop-down menu as soon as I input at least two characters

I am currently utilizing Angular 2 and I am trying to retrieve the names of all restaurants from a dropdown menu. Currently, when I click on the text field, it displays all the results, but I would like it to only show results after I have entered at least ...

A guide on triggering a function when a button is clicked in reactjs

Can anyone please help me with this issue I'm having: how do I execute a function when a button is clicked? I currently have the following code but it's not working export var Modulo = React.createClass({ prom1: function () { retur ...

Switching a conditional className to a styled component

Currently, I am in the process of converting my project from plain CSS to styled components using styled-components. So far, I have successfully converted all of my components except for one. I have looked at various examples on Stack Overflow but none of ...

Refreshing the page results in a 404 error when utilizing React Router

I am currently facing an issue with my web application setup. Back-End My back-end consists of a Node.js/express server that serves files in response to specific requests made to certain routes. Front-End On the front-end, I have React pages that commu ...

Manipulating JSON with ng-model in AngularJS

Let's say I have a simple JSON similar to this: { "Object 0": {} } I am trying to display it as a tree structure. This is the approach I am taking: <span>{{key}}</span> // Object 0 <span>{{value}}</span> // {} <ul> ...

"Tips for retrieving properties from a JSON object that has been converted to a string

I'm facing an issue with retrieving the url from a response in my code. The goal is to use this url for navigation using the router function. Here's the problematic code snippet: const redirectToStripe = async () => { const response = await ...

Utilizing a hidden file-input, IE10 is able to transmit a FormData object via ajax

I'm encountering difficulties when trying to send a form that includes a display:none file-input via ajax. It works fine in Chrome (46.0.2490.71), but not in IE10 (10.0.9200.17492). I've tried various solutions without success, and it's cruc ...

Placing the video at the center of the background image

                    Can someone assist me with a design issue I'm facing? I have two divs within a section. The left div contains a heading and a button, while the right div contains a video. However, when I try to add a background image to ...

managing jquery delays with deferred objects

Using jQuery deferred objects has always been smooth sailing for me and I have a good grasp on how they operate. Recently, I encountered a new scenario where I need to employ them once again. I have a series of similar functions that I am adding to a def ...

Testing Async operations in the browser with Mocha and Chai

I'm having trouble running async tests with mocha. Below is the snippet of my code: describe('Brightcove Wrapper',function(){ describe("#init()", function() { it("Should inject the brightcove javascript", function(callback){ ...

The retrieval process is unable to receive a response from the server

Question: I am encountering an issue with the fetch API in the client-side code. Here is the snippet of the code: window.fetch('/signup', { method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlen ...

Reload the precise URL using JavaScript or jQuery

I need a solution to refresh the current URL after an ajax success. I attempted the following methods: location.reload() history.go(0) location.href = location.href location.href = location.pathname location.replace(location.pathname) However, I encounter ...

Ways to display a collection of random images with a click of a button?

I've created a simple php webpage that is supposed to display random images from my images folder when a button is clicked. However, I'm facing an issue where no images are showing up and I can't seem to pinpoint the problem in my code. ...

Obtain information from an ajax request

I am working on a website where I need to implement a button that checks if the user has specific permissions before opening a new web page in a popup window. In my JavaScript code, I have the following function: function sendAjax(methodName, dataArray, s ...

Enhance your website with interactive AJAX callback animations using jQuery

I've encountered an issue while using a basic AJAX script in jQuery. I want to implement an easeInOut effect for the AJAX callback to change the HTML smoothly, but I'm not sure how to achieve this. Currently, when the response is received, the co ...