Is the behavior of a function with synchronous AJAX (XMLHttpRequest) call in JavaScript (Vanilla, without jQuery) the same as asynchronous?

I'm facing an issue with a file named tst.html and its content:

part two

(purely for demonstration, no extra markup)

The challenge arises when I try to load this file using synchronous AJAX (XMLHttpRequest):

function someFunc() {
    var str = 'part one_';

    var x = new XMLHttpRequest();
    x.open('GET', 'tst.html', false); // Using "false" for synchronous request
    x.onreadystatechange = function() {
        if (x.readyState === 4) {
            switch (x.status) {
                case 200:
                    str += x.responseText.trim();
                    break;

                default:
                    return '';   // Or any desired action
                    break;
            }
        }
    }
    x.send();

    str += '_part three';

    return str;
}

When calling the above function:

alert(someFunc());

// This will output "part one_part two_part three"

This function performs as expected. However, if I move the AJAX call into a separate function:

function ajaxCall() {
    var x = new XMLHttpRequest();
    x.open('GET', 'tst.html', false);
    x.onreadystatechange = function() {
        if (x.readyState === 4) {
            switch (x.status) {
                case 200:
                    return x.responseText.trim();
                    break;

                default:
                    return '';
                    break;
            }
        }
    }

    x.send();
}

function someFunc() {
    var str = 'part one';

    str += ajaxCall();

    str += 'part three';

    return str;
}

And then invoke it:

alert(someFunc());

// This time it returns "part one_undefined_part three"

In this scenario, the function returns before the AJAX completes, mirroring the behavior of asynchronous calls.

I've been searching for solutions like a "Synchronous AJAX function," but nothing helpful has turned up so far.

The use case involves the AJAX call within a recursive function set, where further processing depends on the AJAX response. For example:

function one(url) {
    var x = new XMLHttpRequest();
    x.open('GET', url, false);
    x.onreadystatechange = function() {
        return two(x.responseText.trim());
    }
    x.send();
}

function two(str) {
    var output;

    output += stuff;

    // ... parsing through str
    // ... until finding a match

    if (isURL(match)) {                     
        output += one(match);
    } else if (isFormattedString(match)) {   
        output += two(match);
    }

    output += more stuff;

    // More processing in the output    

    return output;
}

var final = one(url);

In the provided example:

  • the process begins with a URL via one(url)
  • one() outputs a string that's used in two(str)
  • Within two(), the parser can encounter either
    1. another URL, or
    2. a parseable string.
  • Based on this, one of the functions is called
  • The result is added to the final system output

A callback from one() won't resolve this issue since I still need a final return within two().

function one(url, callback) {
    // ... AJAX operations
    {
        callback(two(x.responseText));
    }
}

function two(str) {
    // ... same steps as before

    if(isURL(match)) {
        one(match, function(result) {
            output += result;

            // ... additional processing

            return output;
        });
    }else if(...) {
        // ... continuing previous logic
    }

    // ... more actions
}

Another approach could involve using deferred, yet its application remains uncertain in this context.

Is there a method to enforce JavaScript treating this similarly to other synchronous functions, halting execution until completion? The confusion lies in why this doesn't occur despite declaring the AJAX request as asynchronous.

Thank you for any guidance!

Answer №1

Your inquiry captivated me with its thoroughness (if only everyone dedicated this much effort to asking questions!), but at its core, it can be summarized as follows:

function ajaxCall() {
    var x = new XMLHttpRequest();
    x.open('GET', 'tst.html', false);
    x.onreadystatechange = function() {
        if(x.readyState === 4) {
            switch(x.status) {
                case 200:
                    return x.responseText.trim();
                    break;

                default:
                    return '';
                    break;
            }
        }
    }

    x.send();
}

The use of the return statement in your code is actually returning from the onreadystatechange function, not from the expected ajaxCall function. The key difference lies in the fact that your original code just involved concatenating strings. This adjustment has no direct correlation to moving the statement into its own function.

A word of caution: avoid synchronous AJAX requests! It's crucial to grasp the workings of asynchronous functions, especially through resources like How do I return the response from an asynchronous call?

Answer №2

Issue lies in the outcome of your return

return x.responseText.trim();

The problem arises because the return statement is within the handler and not within the ajaxCall function itself. As a result, it always returns undefined.

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

The request to sign up at http://localhost:3000/api/signup resulted in a 400 (Bad Request

Having recently started working with the MEAN stack, I've run into some issues when trying to send registration data using http.post. Below is my server code: var express = require('express'), bodyParser = require('body-parser' ...

Attempting to bring in HTML through a helper, but Rails doesn't seem too thrilled about it

I have a form that triggers a remote GET request, leading to the display of a modal. The issue I'm facing is that multiple actions can utilize the same model, so I am attempting to employ a helper and jQuery to showcase different data based on what is ...

Error message: Unable to locate local module in node.js subdirectory

Exploring the folder structure within my application https://i.stack.imgur.com/Pkxpg.png Referring to app_modules/bar and app_modules/foo as local modules Root Folder package.json "dependencies": { "body-parser": "~1.18.2", "cookie-parser": "~ ...

Server Receiving Missing Post Parameters

I've developed a straightforward $resource factory. .factory('Order', order) order.$inject = ['$resource', "ApiEndpoint", "UserRecord"]; function order($resource, ApiEndpoint, UserRecord) { return $resource(ApiEndpoint.url + & ...

Stop video and audio playback in an android webview

Is there a way to pause audio and video in an Android WebView without disrupting the page rendering? I have tried various methods but haven't found one that successfully pauses both the sound and the video without affecting the WebView. webView.onPau ...

Guidelines for leveraging AngularJS Decorators to deactivate a button within an Html document

Currently, I am utilizing the blur admin theme and exploring the possibility of using decorators to hide a button without directly modifying the HTML. Despite my efforts, I have been unable to successfully conceal the button. Can someone provide guidance o ...

Attempting to transfer various files using a text box, yet upon submission, the form does not contain any input for the name or date text

The issue I am facing is that although this code successfully saves the file and the name to the database, the textbox values for Name and Date are empty even though they were filled in. Below are the PHP and HTML Files along with JavaScript: index.html ...

ASP.NET MVC: Issue with displaying image list using AJAX call

I'm facing an issue where my images list is not displaying when I call images with an AJAX request. The code works perfectly on page load, but it doesn't display any images on AJAX call. Here is my code: The view markup is: <script> $( ...

Error encountered when attempting to retrieve data from an API route using s3, resulting in an uncaught promise with the message "SyntaxError: Unexpected token < in JSON at position 0

I'm attempting to retrieve a JSON file from an S3 bucket. Here is the API route I'm using to fetch the json file: const {GetObjectCommand, S3Client} = require("@aws-sdk/client-s3"); const client = new S3Client() // Add opts to S3 if nee ...

Build a custom form for the purpose of exporting an HTML file

I am in search of a way to provide my users with various "feature" choices that will assist them in creating an HTML file for an email. I already have the code ready for each feature, but I want users to be able to select a feature (such as Hero Image Head ...

Experiencing issues with Ajax calls in Yii 2, receiving a bad request error (#400)

Here is the code I have written: $(document).on('change', '#tblhotel-int_zone_id', function(e){ var zoneId = $(this).val(); var form_data = { zone: zoneId }; $.ajax({ url: "state", type: "POST", ...

What is the best way to display multiple Google Charts using various data tables within a single PHP document?

I am looking to create multiple charts using data from different sources. The data comes from queries within a PHP file named ajax.php. Below is the code snippet: //JOB POST BY SALARY function jobsalary(){ // Function logic here... } //JOB POST BY J ...

Testing a service resolution in a controller through unit testing

As I attempt to create a test for my home module, I keep encountering an error that reads "unknown provider: service." Interestingly, when I modify resolveSomething in my home module to output a string, the app functions as expected, indicating that the re ...

Sending handlebars variable to the client-side JavaScript file

I am currently working on an application using node.js along with express and handlebars, and I'm trying to find a way to transfer handlebars data from the server to client-side JavaScript files. Here is an example: //server.js var person = { na ...

Transferring data between two functions within a React.js application

I have two functions called getLocation() and getLocationName(). The getLocation() function performs an XMLHttpRequest, and I want to pass the response to the getLocationName() function to display it in a list. getLocationName = (location) => { var ...

Arrange objects in an array according to the order specified in another array

Here is my array of car makes: const makes = [ {id: "4", name: "Audi"}, {id: "5", name: "Bmw"}, {id: "6", name: "Porsche"}, {id: "31", name: "Seat"}, {id: "32", name: "Skoda"}, {id: "36", name: "Toyota"}, {id: "38", name: "Volkswagen"} ] Now, I want to o ...

Greetings! I am looking for information on how to activate CORS in a Ruby on Rails API application deployed on OpenShift for use with an Angular

My current setup involves a script utilizing Angular to display records fetched from a Rails API REST, which is hosted in OpenShift. In my public/.htaccess file, I have included the following directives: Header add Access-Control-Allow-Origin "*" Header a ...

Resizing a webpage to fit within an IFRAME

Having just started learning HTML, CSS, and JavaScript, I am attempting to incorporate a page as a submenu item on my website. Below is the code that I have so far: <!DOCTYPE html> <html> <meta name="viewport" content="width=1024"> ...

The filter function in JavaScript's Array is malfunctioning on Internet Explorer version 7

My web application includes a jQuery plugin that is functioning correctly in Internet Explorer 10 and 11. However, it is not working in IE 7. Upon investigation, I discovered that the value of the filter method is showing as undefined. The line of code th ...

Utilize Ajax datatable to showcase information with the help of CodeIgniter

I am trying to fetch data from a database in my view using ajax, but I am getting the following error message: DataTables warning: table id=users - Requested unknown parameter '0' for row 0, column 0. For more information about this error, please ...