devthorne devthorne - 1 year ago 91
AngularJS Question

Resolve entire chain in each promise in $q.all before resolving next one

I am looping through an array, and in each loop, I add to an array of promises that is then passed into

. Each chain includes a
dialogue and a
. The sequence of events for the user should be confirm() - modal - confirm() - modal. Instead, I'm getting confirm() - confirm() - modal - modal. Also, I'd like a function
to execute after the last modal is closed, but it currently fires as soon as the last
dialogue is closed.

var promiseArr = [];
var selection = []; // [obj1, obj1, obj3...]

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


function getData(i) {
var opts = {}; // selection[i].id is param

return $http(opts)

function onGetSuccess(i) {
return function(result) {
var shouldOpenModal = confirm(selection[i].text);

if (shouldOpenModal == true) {

function openModal() {
var copyPunchesModal = ${
// modal template options

copyPunchesModal.result.then(otherFunc, function () {
console.log("Modal closed");

function refreshSelection() {
selection = [];

I have also tried the following to no avail.

function getData(i) {
var opts = {}; // selection[i].id is param

return $http(opts)

Help is much appreciated.

Answer Source

Q.all doesn't specify the order in which the promises will be resolved. If you want the promises to be completed in the order of the array you need to chain the promises so that the current promise is executed inside the .then() of the previous promise.

You can do this cleanly with reduce.

I've got an answer here for ES6 promises, here it is adapted to Q:

deferred = $q.defer();
return selection.reduce(
    (accumulator, current) => accumulator.then(()=>getData(current)), 

Note that you'll also need to modify your getData function to operate on the object itself (so currentSelection.text instead of selection[i].text, for example)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download