Richard Neumann
Richard Neumann

Reputation: 3381

Wait for nested sub-promises

I am trying to implement a front-end for a web-application API. There are three Ajax-Calls need to be made.

  1. List all groups.
  2. For each group list its members.
  3. From each group's members get the terminals and expand the value.

The three Ajax calls look like this:

  function getGroups () {
    return jQuery.ajax({
      url: "https://webapp.mydomain.com/group?session=" + his.getSessionToken() + "&customer=test"
    });
  }

  function getMembers (group) {
    return jQuery.ajax({
      url: "https://webapp.mydomain.com/group/" + group.id + "/member?session=" + his.getSessionToken() + "&customer=test"
    });
  }

  function getTerminal (terminal) {
    return jQuery.ajax({
      url: "https://webapp.mydomain.com/terminal/" + terminal.tid + "?session=" + his.getSessionToken() + "&customer=test"
    });
  }

I also have the following miscellaneous functions:

  function display (html) {
    document.getElementById('result').innerHTML = html;
  }

  function success (message) {
    display('Success: ' + JSON.stringify(message, null, 2));
  }

  function error (error) {
    display('Error: ' + JSON.stringify(error, null, 2));
  }

Now I face the problem how to chain the respective Promises (actually Deferreds) correctly.

I tried the following:

  function setTerminal (terminals, index) {
    function curry (terminal) {
      terminals[i] = terminal;
    }

    return curry;
  }

  function expandMembers (members) {
    var promises = [];
    var promise;
    var terminals = members.terminal || [];

    for (var i = 0; i < terminals.length; i++) {
      promise = getTerminal(terminals[i]);
      promise.then(setTerminal(terminals, i));
      promises.push(promise);
    }

    return Promise.all(promises);
  }

  function getMembers (groups) {
    var promises = [];
    var promise;

    for (var i = 0; i < groups.length; i++) {
      console.log('Group #' + i + ': ' + JSON.stringify(groups[i]));
      promise = getMembers(groups[i]);
      promise.then(expandMembers);
      promises.push(promise);
    }

    return Promise.all(promises);
  }

  function listGroups (groups) {
    getGroups().then(getMembers).then(success);
  }

This will however not wait for the sub-promises (and actually return a list of empty lists, one for each group).

What I want to achieve is:

  1. Get all groups (getGroups).
  2. For each group get all members (getMembers).
  3. Set members on group object.
  4. For each terminal in the group members, get the verbose terminal information (getTerminal).
  5. Replace brief terminal information with verbose terminal information.
  6. If all above is done, display the groups JSON list.

I am at a loss.

Upvotes: 2

Views: 52

Answers (1)

M&#225;t&#233; Safranka
M&#225;t&#233; Safranka

Reputation: 4106

then() returns a new Promise that resolves when the passed function returns. So if I understood your question correctly, this is what you'll probably want to do:

for (var i = 0; i < terminals.length; i++) {
  promise = getTerminal(terminals[i]);
  promises.push(promise.then(setTerminal(terminals, i)));
}

return Promise.all(promises);

(applied to all your Promise groups)

Upvotes: 1

Related Questions