Leveraging promises to make Ajax calls without repeating code

Would it be possible to create an ajax function without duplicating it? Passing different parameters, which are locations to various files. Then utilizing the promise to combine them into a single object, possibly incorporating the spread operator. Is this achievable?

var myFunctionCalls = 0;

let promiseAjax = new Promise(function(resolve, reject) {

//Could we potentially use a for loop to determine how many times the loadDoc function was called and then push the results to an array?
    function loadDoc(location) {
        myFunctionCalls++;
        console.log("loadDoc was called: " + myFunctionCalls);

        var xyz = new XMLHttpRequest();
        xyz.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                resolve(this.responseText);          
            }
        };

        xyz.open("GET", location, true);
        xyz.send();
    }

    loadDoc("/_js/someitems.json");
    loadDoc("/_js/someMoreItems.json");
})

// Combine the responses into one object using spread operators
promiseAjax.then(function(fromResolve){

    var newObj = JSON.parse(fromResolve);
    console.log(newObj);

})

Answer №1

using the power of Promise.all along with Object.assign,

function fetchContent(url) {
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (this.readyState == 4 && this.status == 200) {
        resolve(JSON.parse(this.responseText));
      } else {
        // resolving with empty object to prevent breaking other requests
        resolve({});
      }
    };

    xhr.open("GET", url, true);
    xhr.send();
  });
}

const fetchContents = (urls) => Promise.all(urls.map(url => fetchContent(url))
  .then(results => {
    // merge all results into a single object
    return Object.assign({}, ...results);
  }));

// usage example
fetchContents([
  "/data/some-data.json",
  "/data/more-data.json"
]).then(function(combinedData) {
  // additional logic here
});

Answer №2

To combine the results of two asynchronous calls and manipulate the resolved data as needed, you can utilize Promise.all().

function fetchData(url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (this.readyState === 4 && this.status === 200) {
        resolve(this.responseText);
      }
    };
    xhr.open("GET", url, true);
    xhr.send();
  });
}

const endpoints = ["/data/first.json", "/data/second.json"];
Promise.all(endpoints.map(endpoint => fetchData(endpoint))).then(responses =>
  console.log(responses);
)

Answer №3

To simplify the process, one can define asynchronous functions that return promises and are easily transferable and recyclable.

An example implementation could be as follows:

async function downloadData(data) {
   ...
   return {...downloadedData};
}

async function processData() {
    const data1 = await downloadData('data1');
    const data2 = await downloadData('data2');
    return {...data1, ...data2};
}

processData().then((combinedData) => {
  ...
})

These functions are versatile, accepting arguments and offering reusability just like any other standard function.

Answer №4

This particular behavior can be achieved using Promise.all along with the power of Promise.all, as well as leveraging the combination of async+await async. Implementing more modern calls like fetch can greatly enhance the readability and cleanliness of the code.

async function loadAll(docs) {
    return Promise.all(docs.map(async doc => {
        const result = await fetch('http://example.com/movies.json');
        return result.json();
    }));
}

(async function() {
    const responses = await loadAll(["/_js/someitems.json", "/_js/someMoreItems.json"]);
    console.log(responses);
})();

Please note: the use of await is restricted to async functions only. Note2: It's important to mention that this code has not been thoroughly tested.

Answer №5

A positive approach would be to share the URL, parameters, and the type of AJAX call (POST, GET, etc) with the method. By doing so, you can effectively utilize the same method for various tasks from your client side by making a single method call.

This content has been referenced from:

https://medium.com/front-end-weekly/ajax-async-callback-promise-e98f8074ebd7

function makeAjaxCall(url, methodType)
{
 var promiseObj = new Promise(function(resolve, reject)
 {
  var xhr = new XMLHttpRequest();
  xhr.open(methodType, url, true);
  xhr.send();
  xhr.onreadystatechange = function()
  {
   if (xhr.readyState === 4)
   {
    if (xhr.status === 200)
    {
     console.log("xhr done successfully");
     var resp = xhr.responseText;
     var respJson = JSON.parse(resp);
     resolve(respJson);
    }
    else
    {
     reject(xhr.status);
     console.log("xhr failed");
    }
   }
   else {console.log('xhr processing going on');}
  }
  console.log("request sent succesfully");
 });
 return promiseObj;
}
enter code here
document.getElementById('userDetails').addEventListener('click', function()
{
 // git hub url to get btford details
 var userId = document.getElementById("userId").value;
 var URL = "https://api.github.com/users/"+userId;
 makeAjaxCall(URL, "GET").then(processUserDetailsResponse, errorHandler);
});

You can also pass a callback method to it, along with an error-handling technique.

function makeAjaxCall(url, methodType, callback)
{
  $.ajax(
  {
   url : url,
   method : methodType,
   dataType : "json",
   success : callback,
   error : function (reason, xhr){
   console.log("error in processing your request", reason);
  }
 });
}
// git hub url to get btford details
var URL = "https://api.github.com/users/btford";
makeAjaxCall(URL, "GET", function(respJson)
{
 document.getElementById("userid").innerHTML = respJson.login;
 document.getElementById("name").innerHTML = respJson.name;
 document.getElementById("company").innerHTML = respJson.company;
 document.getElementById("blog").innerHTML = respJson.blog;
 document.getElementById("location").innerHTML = respJson.location;
});

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

Retrieve the dynamically generated element ID produced by a for loop and refresh the corresponding div

I am facing a challenge with my HTML page where I generate div IDs using a for loop. I want to be able to reload a specific div based on its generated ID without having to refresh the entire page. Here is a snippet of my HTML code: {% for list in metrics ...

What is the best way to modify an array within separate functions in a NodeJS environment?

I am facing an issue where I want to update an object inside the fetchAll() functions and then send it back after successful updation. However, the response I receive is '[]'. var ans = [] Country.fetchAll(newdate,(err, data) => { if ...

The PDF format is experiencing compatibility issues when used with the CSS property for page breaks after:

My PDF with CSS page breaks is not functioning properly, as the pages are not breaking as intended. Removing position:absolute solves the issue but leaves space after each page. I suspect it may be a CSS problem, but I'm unsure. If the issue lies wit ...

Encountering cross-domain issues while integrating AngularJS in flex (web control), and trying to retrieve templates/json (local files)

To provide some background on my current endeavor, I am utilizing a Flex application to serve as a container for a web app. Within this Flex app resides a web controller that loads a complete Angularjs application. All necessary files are stored locally wi ...

Guide on displaying a grid in the center of the screen with a vertical sliding feature

I've noticed certain apps displaying a grid view or form on an alert box with vertical sliding, but I'm clueless about how to make it happen. As far as I know, this can be achieved using jQuery.. Any assistance would be greatly appreciated. Th ...

Next.js is failing to infer types from getServerSideProps to NextPage

It seems like the data type specified in getServerSideProps is not being correctly passed to the page. Here is the defined model: export type TypeUser = { _id?: Types.ObjectId; name: string; email: string; image: string; emailVerified: null; p ...

Importing a newly harvested array from a .js file (array that has been exported)

I followed this procedure with assistance from T.J to resolve my issue To address the problem, I made changes to my process. The steps I took are as follows: I switched from exporting an array through a JS file to saving a JSON file instead. Using the .g ...

What are your thoughts on using inline PHP to assign values to JavaScript variables?

Imagine you have a PHP document and need to determine if the request was made with or without query parameters using JavaScript. Since there is no built-in function to extract values from the URL, you may need to resort to some sort of workaround. While it ...

Encountering issues with displaying the JSON response in the table, receiving an undefined error

When I display the JSON response in a table, I am encountering an issue where it shows undefined. The data received can be either one record or multiple records from the database. Interestingly, the correct output is displayed in the alert box. The Control ...

Searching Firebase by using comparison operators on various fields

const FindFiis = async () => { const data: any[] = []; // Firebase query with inequalities on different fields to retrieve docs. // Objective: Select documents where dividendYield is between 8 and 20 and pvp is less than or equal to 1. ...

Caution: Highlighting Non-ASCII Characters in Your Django Form

Looking to implement client-side Ajax validation for my Django form. The goal is to alert users in real-time if any non-ascii characters are detected as they type in a field. Originally considered using python to check for ascii characters in the form&apo ...

Ways to successfully pass multiple parameters in Nuxt

Within Nuxt.js, when working with the code in pages/posts/_id.vue, it looks like this: <template> ...

Show the dropdown menu with names from the array in the ajax response

<html> <select name="cars"> <option value="34">Volvo XC90</option> <option value="54">Saab 95</option> <option value="12">Mercedes SLK</option> <option value="10">Audi TT</option> </select> ...

Using the ESNEXT, Gutenberg provides a way to incorporate repeater blocks that

If you're like me, trying to create your own custom Gutenberg repeater block with a text and link input field can be quite challenging. I've spent hours looking at ES5 examples like this and this, but still feel stuck. I'm reaching out for ...

Can anyone suggest a more efficient method for detecting expired SESSIONS in JQuery?

After only a few weeks of using JQuery, I've encountered an issue where my login page loads within the existing document when the SESSION expires. This problem never occurred before I started using JQuery. It seems that since I have converted all my d ...

Express functions properly when handling the root route, but encounters issues with sub routes as it sends empty response bodies

Inside the routes.ts file: const router:Router = express.Router() // Route to get all blogs router.get('/',async (req:Request,res:Response)=>{ res.status(200).send("message sent") }) router.get('/admin',async (req:Requ ...

Choosing one item from an array to showcase in a view [Angular]

I've previously inquired about this issue without success. My current challenge involves a store app created with AngularJS. I am trying to implement a feature where clicking on an item will open it in a separate "item" view, displaying only the info ...

The JSON.parse function encounters issues when trying to parse due to a SyntaxError: Unexpected character found after JSON at position 2, causing it to be unable

I've encountered an issue with my JavaScript code when trying to retrieve the value of the details field from JSON data. While all other values are successfully passed to their respective fields, the details field generates the following error: "Unabl ...

Isolating Express.js Requests for Enhanced Security

In my Node.js Express app, multiple users send requests to the server for various actions such as earning points, changing email addresses, and interacting with other users. My server code utilizes several setTimeouts, leading me to question whether diffe ...

Transform an array into an array of objects using the reduce method

optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'] result = [ {start: bengaluru, end: salem}, {start: salem, end: erode}, {start: erode, end: tiruppur}, {start: tiruppur, en ...