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

Having trouble resolving this technical problem in Express.js and JavaScript programming

try { console.log('11111') const { data: { tasks }, } = await axios.get('/api/v1/tasks') console.log('22222 ' + await axios.get('/api/v1/tasks') ) console.log('33333 ' + tasks) There seems to be an issue ...

TypeScript - Indexable Type

Here is an explanation of some interesting syntax examples: interface StringArray { [index: number]: string; } This code snippet defines a type called StringArray, specifying that when the array is indexed with a number, it will return a string. For e ...

Utilize Chrome storage instead of localstorage to generate Parse sessions

I'm currently developing a Chrome Extension that relies on Parse User sessions. Because localstorage is limited to specific domains, I am looking to utilize chrome.storage so the data can be accessed across any site. The existing Parse Javascript SDK ...

Tips for structuring route dependencies in Node.js and Express

Although I have a good grasp of exporting routes to an index.js file, my struggle lies in properly referencing external route dependencies without having to copy them to the top of the file. For instance, if I have the main entry point of the program (ind ...

What is the best way to implement a CSS transition for styles that are dynamically created by React?

I have a situation where I am using a button component that is styled based on a theme provided by a context: The code in Button.js looks like: () => { const theme = useContext(themeContext); // { primaryColor: "blue" } return <button className ...

Tips for decreasing the width of a Grid column in MUI React

I have a total of 8 columns. The first column should be the smallest to accommodate a checkbox and does not require much space. I attempted to adjust the xl, lg, md values to 0.5 but was unsuccessful. Is there an alternative method to change the width of t ...

What are some effective methods for troubleshooting unidentified JavaScript functions within Chrome's performance analyzer?

Currently, I am utilizing Angular 4 and incorporating numerous anonymous arrow functions (() => {}). I am curious if it is feasible to identify these functions in Chrome's performance analyzer without assigning them names. Below is an example of t ...

Ways to highlight a form field only when there is data in my variable

For the validation of email addresses in my form, I have been using a combination of php and ajax. The process involves sending the email value via jQuery to my php file and displaying a message if the email is found in the database. While my code function ...

Issues with importing files have been reported on Node.js version 11.8.0

I'm currently working on a program that utilizes a large object filled with dictionary words. I've decided to import this object from a separate file due to its size, but I encountered an error stating that Node.js doesn't recognize the obje ...

Utilizing Array Elements to Populate the Title Attribute in <TD> Tags

I am trying to display text on hover of a cell in my dynamically created HTML table, using the title attribute. However, instead of reading the contents of the array, it is displaying the array name as a string. Below is the code for generating the table ...

Is there a way to incorporate PHP code into HTML using JavaScript?

When making an ajax request on my form in WordPress/WooCommerce, I am attempting to display an error message when a user has not been found. I have tried using the function username_exist(), but it is not working as expected. The only solution I have found ...

Using a string as a query parameter in Javascript/AngularJS

Hey there! I have a username that I'm passing to retrieve a record from the database. Here's what I have in my controller: $scope.team=function(data) team_factory.getMember.query({}, data.username, function(data){ $scope.team=data; }); And ...

How to transform multi-dimensional arrays to JSON format using JavaScript (and maybe jQuery)

Currently facing a Javascript dilemma where data storage is essential in the following format: MainArray(Array(JavaScript Object, JavaScript Object, etc etc..), Array(JavaScript Object, JavaScript Object, etc etc..), etc etc..) The main array consists of ...

How come I am receiving a null value for isMatch from bcrypt compare even though the two password strings match exactly?

Currently, I am attempting to authenticate a user based on a password. My approach involves using bcrypt compare to check if the user's requested password matches one stored in a MongoDB database. Despite the passwords being identical, I keep receivin ...

Displaying text that follows the cursor on a JavaScript mouseover event

When I hover over the pin with my cursor, the text should move along with the mouse. However, the current position of the text is off and needs to be adjusted to be next to the pin. What is a more accurate way to calculate the correct position? var toolt ...

Once the ajax request is finished, load only the <script> tags that have specific ids

I'm currently implementing infinite-scroll to dynamically load more content which includes <script> tags that need to be executed. To achieve this, I have created the following code as an ajax-callback: JS on load ajax callback: function a ...

The Role of Filling in a Process

I am looking to create a rectangle that fills up gradually every day, increasing by 1% each time. This is the basic concept. My main struggle is figuring out how to fill it up. I need the rectangle to increase by 1% of its width each day. So essentially, ...

Rendering sibling components on Multiple Select Material UI in React

Here is my current challenge: I am trying to implement a multiple select feature with checkboxes in React using Material UI. The desired outcome should resemble the image linked below: https://i.stack.imgur.com/TJl8L.png I have structured my data in an a ...

Error message encountered in Express.js when trying to apply the ejs function: "View is not a constructor"

I am attempting to execute certain tasks before the original app.get function is called. After referring to this page, I applied their method which worked for the most part, except when using a rendering engine. The code snippet below demonstrates what I ...

Mastering the art of exchanging cross-domain ajax data in userscripts

My current approach involves using this code to store and retrieve ajax data from $.ajax({ /* send data */ url: "http://api.openkeyval.org/store/", data: "test-key-data=" + JSON.stringify([123,456]), dataType: "jsonp", ...