0

I am having a recursive function which works well and get all the results that I need. once it get's into the second "then" block it logs all the results. However the "return deferred.promise" happens before the data has been loaded, which kind of confuse me as the promise will only be resolved after the data has been loaded. If I move the return deferred.promise up in the 2nd then block, the consuming code tell me this method is not thennable. kKind of confused which part I am missing, any help will be much appreciated.

The code

 function getUserGroups(groups, nextLink) {
            var deferred = $q.defer();
            var intermediaryGroupResult = groups;
            var endpoint = '';
            if (nextLink != '' && nextLink !== undefined) {
                endpoint = nextLink;
            } else {
                endpoint = config.baseGraphApiUrl + "me/memberOf?$select=id,displayName,securityEnabled";
            }
      

            (function (intermediaryGroupResult) {
                $http.get(endpoint).then(function (result) {

                    var dataNextLink = result.data['@odata.nextLink'];
                    var resultsFromGraph = result.data.value;

                    for (var i = 0; i < resultsFromGraph.length; i++) {
                        intermediaryGroupResult.push(resultsFromGraph[i]);
                    }

                    if (dataNextLink != '' && dataNextLink !== undefined) {
                        getUserGroups(intermediaryGroupResult, dataNextLink)
                    } else {
                        console.log('groups', intermediaryGroupResult);
                        return intermediaryGroupResult;
                    }
                }).then(function (allGroups) {
                    console.log('all groups', allGroups)

                    deferred.resolve(allGroups);
               
                });
            })(intermediaryGroupResult);

         
            return deferred.promise;
        }

The console: enter image description here

Rodney Wormsbecher
  • 897
  • 2
  • 17
  • 39
  • The whole idea of promises is that you can return them before resolving them. – Bergi Jul 21 '20 at 12:29
  • Avoid the [deferred antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Jul 21 '20 at 12:30
  • 1
    You're missing to `return` the recursive `getUserGroups(intermediaryGroupResult, dataNextLink)` call from the `then` callback. – Bergi Jul 21 '20 at 12:31
  • @Bergi Thank you for the pointer, it works now. As for using deferred, I stopped using it for about 3 years now, unfortunately I have to update a legacy system that does not have babel / async/await yet. Rewriting the code back to regular promises within AngularJs is outside the scope. – Rodney Wormsbecher Jul 21 '20 at 13:04

2 Answers2

0

In javascript, there is very little blocking code. What that means is that the http request will run in the background, but your code will still continue execute. What's happening is that you're returning an unresolved promise before the data loads, but it'll resolve when the data loads. This is fine, you just have to use .then on the result of the function call.

Aplet123
  • 33,825
  • 1
  • 29
  • 55
0

A few pointers:

  • the Deferrerd is unnecessary. $http.get().then() returns a Promise, which can itself be returned by the function.
  • the IIFE is unnecessary. Presumably, you are trying to ensure that the original groups passed to the function is not mutated.
  • to create a copy of groups with additional members from result.data.value use Array.prototype.concat() and spread syntax as follows; [].concat(...groups, ...result.data.value).
  • the recursive call to getUserGroups() is missing a return.

With a couple of further simplifications, the function can be written as follows:

function getUserGroups(groups, nextLink) {
    return $http.get(nextLink || config.baseGraphApiUrl + "me/memberOf?$select=id,displayName,securityEnabled")
    .then(function(result) {
        var intermediaryGroupResult = [].concat(...groups, ...result.data.value);
        var dataNextLink = result.data['@odata.nextLink'];
        return dataNextLink ? getUserGroups(intermediaryGroupResult, dataNextLink) : intermediaryGroupResult;
    });
}
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44