Search code examples
javascriptangularjsangularjs-scopeangular-resource

Get data by angularjs $resource


I have the following angularJS function that get data by $resource ,it works and push this data to vm.data array, ,but when I try to get vm.data in controller i get null ,This last line of the following code print null value

   function loadAll() {
    Questiongroup.query({}).$promise.then(function(group){
        console.log(group);
        for(var i=0;i<group.length;i++){
           var grouptitle=group[i].title
            Question.questionsByQuestionGroup({id:group[i].id}).$promise.then(function(question){
                vm.question = question; 
               for(var j=0;j<question.length;j++){
                   vm.data.push({ group: grouptitle, question: question[j].question , questiontype: question[j].type });

                   console.log(vm.data)      //this line print correct data 
                   }
         });
        }
      });
    }

    loadAll();
    console.log(vm.data);         //This line print null

Solution

  • The reason that last console.log prints null is that it executes before the functions given to the .then methods. The functions given as arguements to .then methods are invoked by the $q service after the data returns from the server.

    The loadAll function should return a derived promise which can be used to retrieve the vm.data after being assembled. This involves chaining promises and using the $q.all method.

    function loadAll() {
        var topPromise = Questiongroup.query({}).$promise;
    
        var derivedPromise = topPromise.then(function(group){
            var promiseList = [];
            console.log(group);
            for(var i=0;i<group.length;i++){
                var itemPromise  = getItemPromise(group[i]);
                promiseList.push(itemPromise);                        
            };
            //return $q.all promise for chaining
            return $q.all(promiseList);
        });
    
        //return promise
        return derivedPromise;
    };
    

    Then use the returned promise.

    var loadAllPromise = loadAll();
    
    loadAllPromise.then(function (vmData) {
        console.log(vmData);
    });
    

    The above example shows how to create a promise that returns an array of data from an array of promises. It is intuitively obvious to extend that to multiple levels of iteration.


    AngularJS $q.all also works with hashes.

    function loadAll() {
        var topPromise = Questiongroup.query({}).$promise;
    
        var derivedPromise = topPromise.then(function(group){
            var promiseHash = {};
            console.log(group);
            for(var i=0;i<group.length;i++){
                var itemPromise  = getItemPromise(group[i]);
                promiseHash[group[i].id] = itemPromise;                        
            };
            //return $q.all promise for chaining
            return $q.all(promiseHash);
        });
    
        //return promise
        return derivedPromise;
    };
    

    The above example returns a promise that contains a hash (associative array) of data.

    loadAllPromise.then(function (dataHash) {
        console.log(dataHash);
    });
    

    From the Docs:

    all(promises);

    Combines multiple promises into a single promise that is resolved when all of the input promises are resolved.

    Parameters

    An array or hash of promises.

    Returns

    Returns a single promise that will be resolved with an array/hash of values, each value corresponding to the promise at the same index/key in the promises array/hash. If any of the promises is resolved with a rejection, this resulting promise will be rejected with the same rejection value.

    --AngularJS $q Service API Reference -- $q.all