Executing a callback in AngularJS after multiple HTTP requests have been completed using a forEach loop

I am trying to update multiple items within a foreach loop by sending HTTP requests, and I need a callback once all the requests are complete. Despite searching on Stack Overflow, I haven't found a solution that works for me.

Here is the snippet of my code:

$q.all(_($scope.students.items).each(function(item) {
   $scope.student.update(); //this triggers an HTTP call
})).then(function() {
   // I'm in need of a callback at this point
   alert("complete"); //this should only be displayed after all students have been updated, but it appears before all network calls are finished
});

Below is a generic update function example:

self.update = function(item, callback) {
   that.post(item, self.getUrl("update"), function(err, data) {
      if (self.formatter) {
         data = self.formatter(data);
      }
      callback(err, data);
   });
};

Does anyone have any suggestions or solutions to this issue?

Answer №1

In the update() function, don't forget to include a return keyword so that it returns a promise. Additionally, ensure that the that.post() function also returns a promise:

self.update = function(item, callback) {
   return that.post(item, self.getUrl("update") , function(err, data) {
      if (self.formatter) {
         data = self.formatter(data);
      }
      callback(err, data);
   });
 };

With this adjustment, the following code snippet should work as intended:

var promises = [];
_($scope.students.items).each(function(item) {
   promises.push($scope.student.update());
})
$q.all(promises).then(function() {
   alert("complete");
});

Answer №2

$q.all(_.map($scope.students.items, function(student) {
   return student.update();
})).then(function() {
   //all updates have been completed
});

In order for the code above to work, the update function for each item in $scope.students.items must return a promise. It should look something like this:

function update() {
   return $http( ... );
}

Answer №3

For another approach, consider implementing the following code snippet using the map function:

$q.all(_($scope.students.items).map(function(item) {
  item.update();
})).then(function() {
  alert("complete");
});

The code has been updated with a new snippet incorporating methods that provide simple promises. There are two ways to achieve this task:

  • Creating an array of promises and utilizing q.all
  • Utilizing q.all along with map

angular.module('demoApp', []).controller('DemoController', function($scope, $q, $timeout) {
  var a = function() {
    var deferred = $q.defer();
    console.log('Executing a');
    deferred.resolve();
    return deferred.promise;
  };
  var b = function() {
    var deferred = $q.defer();
    console.log('Executing b');
    deferred.resolve();
    return deferred.promise;
  };
  var c = function() {
    var deferred = $q.defer();
    console.log('Executing c');
    deferred.resolve();
    return deferred.promise;
  };
  var f = [{
    call: a
  }, {
    call: b
  }, {
    call: c
  }];

  $scope.mapTest = function() {
    $q.all(f.map(function(item) {
      return item.call();
    })).then(function() {
      console.log("complete");
    });

  };
  $scope.promisePush = function() {
    var promises = [];
    angular.forEach(f, function(item) {
      promises.push(item.call());
    });
    $q.all(promises).then(function() {
      console.log('complete');
    });
  };


});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="demoApp">
  <div ng-controller="DemoController">
    <button ng-click="mapTest()">Q.all using map</button>
    <button ng-click="promisePush()">Q.all using promise push</button>
  </div>
</body>

Answer №4

To optimize efficiency, it is recommended not to send multiple ajax calls within a foreach loop. Instead, consolidate the updates into a single ajax request named "studentsUpdate" and handle the response by iterating over the student collection to update the data accordingly. This approach promotes best practices by reducing the number of ajax calls made.

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

Adding a C# variable to a URL in a Razor view using jQuery

My Razor page looks like this: @{ ViewData["Title"] = "mypage"; string ApiAddress = "https://localhost:8114/api/"; } <div> ... </div> @section Scripts{ <script> functio ...

JavaScript: An object containing a unified handler for all method invocations

Let me explain further. Math.add(2, 2) //4 Math.multiply(4, 9) //36 Whenever a method in the Math object is invoked, it triggers a central processor that interprets the function name to determine its action. Can an object execute a default function when ...

What is the best way to transfer an object from the view to the controller in AngularJS and ASP.net MVC

How to pass an object with a specific amount of data from the View to the Controller using ASP.net MVC and AngularJS VIEW var Person = {}; Person.IdPerson = 69425; Person.Year = new Date().getFullYear(); $http.post('/API/Update_Person', { para ...

Creating distinct short identifiers across various servers

Utilizing the shortid package for creating unique room IDs has proven effective when used on a single server. However, concerns arise regarding the uniqueness of IDs generated when utilized across multiple servers. Is there a method to ensure unique ID g ...

The jQuery remove function will only take effect on the second click following an AJAX request

I'm facing an issue with my jQuery code where two divs contain lists of links, triggering AJAX calls to append JSON data to a separate div. Upon clicking a link, the corresponding link div should hide. There's also a third div with the class "pan ...

Attempting to grasp the sequence in which setTimeout is ordered alongside Promise awaits

I've been puzzling over the sequence of events in this code. Initially, I thought that after a click event triggered and Promise 2 was awaited, the for loop would resume execution once Promise 1 had been resolved - however, it turns out the outcome is ...

Exploring the capabilities of NodeJS together with the fetch function of Backbone

I have a code snippet for the front-end using fetch: var MyModel = Backbone.Model.extend(); var MyCollection = Backbone.Collection.extend({ url: '/questions', model: MyModel }); var coll = new MyCollection(); ...

The text becomes distorted and unreadable after the function is applied. It is impossible to decipher the message

There is a function called getResourceText(''), which takes a key as an argument. This function provides a translation of the requested text when it is called. setFilterName = (isFilterChanged, buttonId, filterName) => { switch (filterName ...

Leverage variables in JavaScript to establish a unique style

function AdjustScale(){ scaleX = window.innerWidth / 1024; scaleY = window.innerHeight / 768; element = document.getElementById("IFM"); element.style.transform = "scale(" + scaleX + ", " + scaleY + ")"; } I'm facing an issue with thi ...

Select three random items from a string array list along with their corresponding indexes using TypeScript in Angular

Consider this example: I am working with a string array const groceries = [ 'milk', 'coriander', 'cucumber', 'eggplant', 'carrot', 'brinjal', 'on ...

Strategies for Returning Multiple Values from a Function in JavaScript

Thanks in advance I am wondering how to extract multiple values from a code block using JavaScript. I am unsure if I need to use an array or something else as I am new to JS. Please consider the following HTML code: <div class="row"> ...

Error encountered during the prerendering process on Vercel's Next.js build

While trying to compile my website on Vercel, I encountered a pre-rendering error during export. Does anyone know why this is happening and can provide assistance? Here is the link to my GitHub repository where all the code is stored: https://github.com/M ...

Navigating through the endless scroll behavior in Twitter using CasperJS (PhantomJS)

Having trouble with infinite scrolling on Twitter, as the page is not loading new content even when scrolling to the bottom. To test if any content loads at all, I have used the following code snippet: casper.open('https://twitter.com/<account> ...

Retrieve JSON data by making an AJAX request to a PHP file using the POST method

I am looking to extract data from a form using an AJAX call. The information is received in PHP as a string that looks like: 'fname':'abc','lname':'xyz','email':'','pass':'',& ...

Creating an object and setting its prototype afterwards

While exploring examples and questions online about prototypal inheritance, I noticed that most of them involve assigning prototypes to constructor functions. One common pattern is shown in the code snippet below: Object.beget = function (o) { var F = ...

JavaScript Numbers Having Strange Behavior

Insight The highest integer that can safely be stored in JavaScript is 9007199254740991 link Dilemma 1000000000000 === 999999999999.999999 // Returns true 1000000000000 === 999999999999.99999 // Returns true 1000000000000 === 999999999999.9999 // Re ...

Navigating File Paths in Node.js

My directory structure is as follows: Main > models > file1.ejs | |> routes > file2.ejs In my code, I'm trying to require file1 from file2 like this: const variable = require("../models/file1.ejs). But what if I don't want to ...

Unexpected Type Error: Unable to Assign 'Render' Property to Undefined

At the moment, I am encountering these specific issues: An Uncaught TypeError: Cannot set property 'render' of undefined The element #main cannot be found This is the code that I currently have. Despite looking for solutions from various sourc ...

Utilizing the power of AngularJS in conjunction with the Edmunds Media API to retrieve stunning

Scenario: Utilizing a Rails application and $http.get in AngularJS to retrieve photos from the Edmunds.com MEDIA API. GOAL: To use ng-repeat to cycle through the vehicle photos. ISSUE: While I am able to successfully fetch a single image, I am struggling ...

When a link is right-clicked, the window.opener property becomes null

Currently, I am utilizing the window.opener property in JavaScript to update the parent window from a child window. The parent window simply consists of a table with data and a link to open the child window. When the child window is launched, a JavaScript ...