Looping through and sending multiple post requests

Is it possible to send post requests in a loop but only have the last request trigger the callback function?

What am I missing here?

this.assignAUnits = function(){
        var currentIncidentId = this.incident.incidentId;
        for (var i=0; i< this.selectedAvailableUnits.length; i++){
            var unit = this.selectedAvailableUnits[i];
            var unitId = unit.unitId;

            var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId

            $http.post(url).then(function(response) {
               DOING SOMETHING

            }, function(error) {
                alert(error);
            });          
        }
    };

Answer №1

To solve this issue, utilize a `closure`. Let me demonstrate with a simple example:

// JavaScript on Client-Side
window.onload = function() {
    var f = (function() {
        for (i = 0; i < 3; i++) {
            (function(i){
                var xhr = new XMLHttpRequest();
                var url = "closure.php?data=" + i;
                xhr.open("GET", url, true);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        console.log(xhr.responseText); // Outputs: 0, 1, 2 
                    }
                };
                xhr.send();
            })(i);
        }
    })();
};

// Server-Side (PHP in this case)
<?php 
    echo $_GET["data"];
?>

In your specific scenario, wrap the asynchronous call/function with a closure like so:

for (var i=0; i< this.selectedAvailableUnits.length; i++) {

    (function(i) {    // <--- key point

        var unit = this.selectedAvailableUnits[i];
        var unitId = unit.unitId;
        var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId
        $http.post(url).then(function(response) {
            // Perform actions here
        }, function(error) {
            alert(error);
        });

    })(i);    // <---- (the i variable might be omitted if it's not needed)

}

The following section is unrelated to the original question but addresses comments related to this answer.


An example shared on jsFiddle, as discussed in the comments below, appears to have some issues and doesn't showcase the intended functionality.

A detailed analysis reveals discrepancies in the output behavior of the code snippet provided, leading to multiple instances of 'Hello Kitty' being displayed unexpectedly. This inconsistency raises questions regarding the underlying mechanisms at play within the code implementation.

Further optimizations and corrections are necessary to affirm the reliability and accuracy of the script execution in varied environments such as jsFiddle.

By revisiting the coding structure and making relevant adjustments, a more stable and predictable outcome can be achieved, ensuring the desired results align with the expected outputs.

Answer №2

Unfortunately, I am not familiar with AngularJS, but I have found success using these two methods which involve posting data through jQuery or base XMLHttpRequest:

<button onclick="sendWithJQuery()">send</button>
<ul id="container"></ul>
<script src="/vendor/bower_components/jquery/dist/jquery.js"></script>
<script>
  //Sending data using XMLHttpRequest
  function send(){
      for (var i = 1; i <= 10; i++){
          var xhr = new XMLHttpRequest();
          xhr.open('POST', '/test/' + i);
          xhr.onreadystatechange = function(){
              if (this.readyState != 4){
                  return;
              }
              var li = document.createElement('li');
              li.appendChild(document.createTextNode('client time:' + new Date().toISOString() + ', data: ' + this.responseText));
              container.appendChild(li);
          }
          xhr.send();
      }
  }

  //Sending data using jQuery
  function sendWithJQuery(){
      for (var i = 1; i <= 10; i++){
          $.ajax({
          url: '/test/' + i,
          method: "POST",
          statusCode: {
              200: function (data, textStatus, jqXHR) {
                  var li = document.createElement('li');
                  li.appendChild(document.createTextNode('client time:' + new Date().toISOString() + ', data: ' + JSON.stringify(data)));
                  container.appendChild(li);
              },
              500: function (data, textStatus, jqXHR) {
                  alert('Internal server error');
              }
          }
      });
      }
  }
</script>

Server-side code using Node.js:

router.post('/test/:i', function(req, res) {
    var i = req.params.i;
    var t = new Date().toISOString();
    setTimeout(function(){
        res.send({i: i, t: t});
    }, 1000);
});

Answer №3

When you attempt to utilize a variable that changes, such as url, within a for-loop, there are some considerations to keep in mind.

If a closure is not used inside the loop, only the final value of your for will be passed to the $http.post function call.
Closures within loops can present challenges. For more insights and details on this topic, refer to this question JavaScript closure inside loops - simple practical example and conduct further research online.

Your code may need adjustments similar to the following:

var doHttpRequest = function(url) {
  $http.post(url).then(
    function(response) {
      // HANDLE RESPONSE
    },
    function(error) {
      alert(error);
    });
}

this.assignUnits = function() {
  var currentId = this.incident.incidentId;
  for (var i=0; i< this.selectedAvailableUnits.length; i++) {
    var unit = this.selectedAvailableUnits[i];
    var unitId = unit.unitId;

    var url = '/incident/' + currentId + '/assignUnit/' + unitId

    doHttpRequest(url)
  }
};

Update: additional resource
I faced a similar issue recently, which you can explore here: Angular JS - $q.all() tracking individual upload progress

Answer №4

It seems like a common problem related to closure in this scenario. For more information, you can visit this link

Additionally, it is recommended to use $resource instead of $http (ng-resource).

Take a look at the provided example on how to post data in a for loop using a resource.

      for(var i=0; i<$scope.ListOfRecordsToPost.length; i++){       
          var postSuccessCallback = function(postRec) { 
              console.info('Posted ' + postRec);
          }($scope.ListOfRecordsToPost[i]);

          lsProductionService.post({}, postSuccessCallback); 
      }

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

I'm looking to showcase the list in a navigation bar by clicking on the hamburger menu. I want to include the 'home' and 'about' text specifically

Having trouble implementing the hamburger menu functionality in my HTML/CSS project. When clicked on a shrunken screen, I want the 'Home' and 'About' text in the nav to appear stacked on top of each other. JS is causing me some difficul ...

Animate the Transition Views with Angular.js

I recently started learning Angular and have been going through the basic tutorials on their official website. However, I haven't come across any tutorials that focus on animating view transitions. I am particularly interested in having my current vie ...

Choosing a random element in React: A step-by-step guide

I'm currently working on a dynamic website that aims to load a random header component upon each refresh. Despite my various attempts, the functionality operates smoothly during the initial load but consistently throws this error on subsequent refresh ...

Discovering the method to retrieve a previous month's date within a VueJs application using Javascript

Can someone guide me on how to retrieve the date of the past month using Vue? This is the code I currently have: import SomeTable from "./table/SomeTable"; export default { name: "Cabinets", components: {SomeTable}, data() { return { ...

Using CloudantDB and NodeJS to retrieve data based on specific id

I recently set up a NodeJS cloudantDB web starter on bluemix. After that, I managed to successfully retrieve data from cloudantDB using an API, but it returned all the data available. Here's an excerpt from my JavaScript file: JavaScript file: app.g ...

Best practices for incorporating and leveraging node packages with Laravel Mix

As I embark on my Laravel (v 8.x) Mix project, I am encountering challenges when it comes to incorporating JavaScript from node modules. To kick things off, here is a snippet from my webpack.mix.js: mix.js('node_modules/mxgraph/javascript/mxClient.mi ...

A guide on using key arrows in JavaScript to navigate and focus on elements

When working on my HTML project, I have a list of elements that I want to be able to select using the arrow keys. I've included my code here for reference: [http://jsfiddle.net/T8S7c/] What I'm trying to achieve is when the arrow keys are press ...

Having difficulty with my async custom react hooks. Is there a way to wait for the result of one hook before using it in another hook?

Having some difficulty working with custom react hooks. I've created 2 custom hooks - one for fetching an ID and another for fetching a profile using the previously fetched ID. Since the second hook is dependent on the ID, I need to await the promise ...

Every time I try to read a file using JavaScript, I keep running into the error: "Uncaught TypeError: fs.readFile is not a function." It's really frustrating

const fileSystem = require('fs'); fileSystem.readFile('analogData.txt', 'utf8', (error, content) => { if (error){ console.log(error); } else console.log(content); }); I am attempting to retrieve data f ...

Deliver an extensive JSON reply through a Node.js Express API

When dealing with a controller in a node/express API that generates large data sets for reports, reaching sizes as big as 20Mb per request, maintaining a positive user experience becomes essential. What strategies can be employed to efficiently handle suc ...

The provisional headers provided by the local passport authentication strategy offer an added layer

When I send a POST request from my frontend with a username and password object, here is the code: const login = data => ( axios.post('http://localhost:3000/v1/user/login', data) .then(response => response.data) .catch((err) => ...

Google App Engine does not properly interpret PHP code when making AJAX requests

I am currently facing an issue with using AJAX request on Google App Engine. In my local development environment, everything works fine and the request is correctly interpreted. However, when I deploy the code to production, the AJAX request renders the co ...

What purpose does the div tagged with the class selection_bubble_root serve in Nextjs react?

Just starting out with Nextjs and setting up a new Next.js React project. I used create-next-app to initialize the code base, but then noticed an odd div tag with the class 'selection_bubble_root' right inside the body. Even though its visibility ...

Exploring Ways to Return to a Modal Using AngularJS and Ionic Framework

In my current project, I am faced with a challenge involving an array of items displayed on a page. Each item, when clicked, triggers a modal to open, presenting the user with a button that navigates to a separate controller and view. Upon clicking the ba ...

Enhancing Vue.js Scripts with Laravel Localization Language-Strings

Within my vue.js script, I have successfully implemented a sweetalert using two Laravel localization language strings. Now, I am attempting to utilize the same language strings as data properties in another vue.js component script. The issue arises when t ...

Efficiently handling jsonwebtoken errors in node and express

Here is the verification function I've created: exports.verifyToken = function(req, res, next){ var token = req.body.token; jwt.verify(token, config.sessionSecret, function(err, decoded) { if(err){ return next(err); }else{ ...

Deciphering the significance behind the initial five lines of code in jQuery

Curiosity piqued, I delved into the jQuery code only to be met with this puzzling snippet: ! function(a, b) { "object" == typeof module && "object" == typeof module.exports ? module.exports = a.document ? b(a, !0) : function(a) { i ...

animations are not triggering when using ng-click inside ng-repeat, is there a reason why the event is not firing?

Check out the code in jsFiddler here After reviewing the code, it's clear that when the add button is clicked, a new item is pushed to the $scope.p. Each item in the ng-repeat loop has an event-binding and everything functions correctly. However, onc ...

Can you explain the compatibility between comet and PHP?

As I utilize Comet iframe, I simply send script tags from the backend PHP file to the frontend where JavaScript displays them. I would appreciate it if someone could provide a concise explanation of how the comet server fits into the equation and how comm ...

Updating state in child components from a different child component in React

How can I update the state of one child component when a button is clicked in another child component, both sharing the same parent component? import React from "react": import A from "..."; import B from "..."; class App extends React.Component { r ...