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

Creating a window.variable in a jQuery ajax callback using CoffeeScript

This particular project is built using rails and backbone-on-rails framework. Despite my efforts, I have been facing an issue with setting a global variable in a response callback function. Here's what I have attempted so far: 1) Initialization of t ...

The error code 13:5 indicates that the "Home" component has been registered in the Vue application but is not being used, leading to the error message "vue/no-unused-components"

I encountered this issue while working with Vue for the first time. I was attempting to construct a website using Vue/CLI by reorganizing and building from the inside out. However, I am unfamiliar with Vue and unsure how to resolve this error. The changes ...

Using JQuery Ajax to post an array

I have searched extensively for solutions, but none seem to fit my situation. Currently, I am utilizing the Jquery-Plugin DataTable with multiple tables within a form. The exact number of tables is unknown. The challenge lies in retrieving form data from ...

"Key challenges arise when attempting to execute the node app.js script through the terminal due to various middleware compatibility

I'm a beginner with node.js and I've encountered an issue while trying to run my node app.js file after incorporating a new file named projects.js which contains the following JS code: exports.viewProject = function(req, res){ res.render(" ...

Is it possible to insert clickable links within the content of a Twilio text message?

Currently, I am utilizing Twilio and Express to send programmable SMSs to the users of my web application. I'm curious if it's possible to include hyperlinks within the body of these text messages. Is there a method to achieve this? I have attem ...

Is there a way to use a specific keyboard input to alter the characteristics of shapes on my webpage?

Is there a way to change certain attributes of a shape onscreen when a specific key is pressed by the user? For example, can I make it so that pressing "a" changes the color of the shape? I attempted to modify a mouse rollover event to work with the desir ...

Is there a way to remove specific elements from an array without using jQuery?

I've recently started diving into Javascript, experimenting with Tampermonkey scripts for the past week. The webpage I'm currently working on features dynamic elements that appear randomly with each page load. Sometimes only one element like "he ...

Transforming a TypeScript enum into an array of objects

My enum is defined in this structure: export enum GoalProgressMeasurements { Percentage = 1, Numeric_Target = 2, Completed_Tasks = 3, Average_Milestone_Progress = 4, Not_Measured = 5 } However, I want to transform it into an object ar ...

Upgrade to the most recent versions of packages using npm

When using npm install --save <package_name>, it typically installs the latest stable version of the package. If you want to specifically install the most recent release, such as Bootstrap v4, you would need to use npm install <a href="/cdn-cgi/l ...

Can a Typescript class type be defined without explicitly creating a JavaScript class?

I am exploring the idea of creating a specific class type for classes that possess certain properties. For example: class Cat { name = 'cat'; } class Dog { name = 'dog'; } type Animal = ???; function foo(AnimalClass: Animal) { ...

Alter the app's entire background color in React.js with a button click

I am facing an issue with changing the background color of my entire React App when a button is clicked. Currently, I am able to change the color of the button itself but not the background. I have imported the App.css file into my project and I am looking ...

ESLint detected a promise being returned in a function argument where a void return type was expected

I'm encountering a recurring error whenever I run my ESLint script on multiple routers in my server. The specific error message is as follows: error Promise returned in function argument where a void return was expected @typescript-eslint/no-misuse ...

The most effective method for positioning a child element to the left and top using Flexbox grid

I am currently working on visualizing queues and processes within a system. Each process is associated with a specific queue from which it retrieves data. I aim to create a layout similar to the following: https://i.stack.imgur.com/BXyts.png However, I a ...

A guide to creating a TypeScript redux middleware class

As specified in the typescript definition for Redux, these interfaces must be implemented to create middleware: /* middleware */ export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> { dispatch: D getState(): S } /** * A midd ...

Display/Modify HTML form

Looking for advice on how to create an interactive HTML form that displays data and allows users to edit it by clicking 'Edit' before submitting changes. Any suggestions on how to implement this functionality? ...

When I try to pass a variable as a prop to another .js file, it mysteriously transforms into an undefined value

Upon successful login, my app file sets the isAuthenticated variable to true and redirects to the /admin page. The Firebase API call is functioning as expected, allowing access only with a valid username and password. The issue arises when I try to hide t ...

Can you explain the mechanics behind the animation of the upvote button on steemit.com?

Behold the upvote button of steemit.com: <span class="Icon chevron-up-circle" style="display: inline-block; width: 1.12rem; height: 1.12rem;"> <svg enable-background="new 0 0 33 33" version="1.1" viewBox="0 0 33 33" xml:space="preserve" xmlns=" ...

Error 404 when Making an Ajax Request in Yii2

I'm trying to implement AJAX in Yii2 (a PHP framework) but I am facing issues with the following code. This is my view file (PHP): <script> var url1='<?php echo Url::toRoute('Agehi/Ajaxshahr'); ?>'; </script> & ...

What benefits do Adobe Creative Cloud apps offer for developing interactive content in AEM?

My client recently transitioned to AEM for their website, and we are tasked with creating an interactive HTML5 'component' to be embedded on a page. While we have previously used custom HTML5 for components, integrating them into pages on the old ...

Why isn't my textarea in jQUERY updating as I type?

On my website, I have a comment script that is not functioning correctly in some parts of the jQuery/JavaScript code. Instead of posting an edited comment to PHP, I created a notification window to test if the value passed through is actually changing. W ...