1

So it seems I still don't understand promises correctly. I am using the angular resolve to prevent controller loading the view before the promise is resolve but its not working as expected. What I am doing wrong?

Here is my service

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
        var items;
        return {
            get: function(params) {
                var defer = $q.defer();
                $timeout(function() {
                    getCommonList.helpdesk.priority().success(function(result) {
                        console.log('waited for long tym ');
                        defer.resolve(result);
                    });
                }, 0);
                return defer.promise;
            },
        }
    });

Call from controller

helpdeskPriority.get().then(function(data) {     
            console.log(data);
        });

my priority function

priority: function() {
                        return $http({
                            url: urlc.getListing.priority,
                            data: {
                                "params": JSON.stringify({})
                            },
                            method: 'POST',
                        });
                    },
Pradeep Jaiswar
  • 1,785
  • 7
  • 27
  • 48

3 Answers3

1

The main thing you didn't quite get was how .factory() works. It should be given a function that will return a value. It doesn't need a .get() function of its own, Angular will create a provider object for you with {$get: <your factory function>}.

Then you need to realise that when you use resolve, the dependency should resolve to a promise. This means that when the injector gets a value for the helpDeskPriority dependency, it will get a promise as the value (because it calls the $get method of the provider, which is your factory function). The resolve mechanism will wait for that promise to be resolved before running your controller with the helpDeskPriority dependency equal to the value it was resolved with.

So change your factory code to:

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
        var items;
        var defer = $q.defer();
        $timeout(function() {
             getCommonList.helpdesk.priority().success(function(result) {
                 console.log('waited for long tym ');
                 defer.resolve(result);
             });
        }, 0);
        return defer.promise;
    });

And then your controller becomes:

 function myController($scope, ..., helpDeskPriority) {
      console.log(helpDeskPriority); // will already have the correct value
 }
GregL
  • 37,147
  • 8
  • 62
  • 67
  • hey @Gregl. That looks good !! I tried same but not able to get it running .Can u tell what i may b missing ? i am using the required js. is that effecting something ? i have added my priority function in question !! thanks – Pradeep Jaiswar Apr 11 '14 at 06:52
  • Can you also add your route definition to the question so that I can see how you are trying to use `resolve`? I just need the one route you have that uses `resolve`, not all the routes. – GregL Apr 11 '14 at 07:38
  • Gregl..I have not put this on resolve yet. Do i need to put this on resolve ? if yes can tell how to put there ? becouse there are many service like this page ? so i need to put all of them to resolve ? – Pradeep Jaiswar Apr 11 '14 at 08:10
  • @GregL: the `get()` function has nothing to do with the `$get` function that is expected in an provider and it is not forbidden to name a service function `get`. Furthermore, it is not a good idea to return a promise as the return value of a service-factory. A service should be rather an object containing methods, which are the service operations. And Pradeep Jaiswar did good, even if the name `get()`is rather confusing. – jeromerg Apr 11 '14 at 12:14
0

Put your code into a closure may help you

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
  var items;
  return {
    get: function(params) {
      var defer = $q.defer();
      (function (deferred, list) {
        $timeout(function() {
          list.helpdesk.priority().success(function(result) {
            console.log('waited for long tym ');
            deferred.resolve(result);
          });
        }, 0);
      })(defer, getCommonList);
      return defer.promise;
    },
  }
});
long.luc
  • 1,191
  • 1
  • 10
  • 30
-1

You code is correct. You just need to set scope-variables in then() callback that are bound to your template. Angularjs will automatically trigger a refresh:

helpdeskPriority.get().then(function(data) {     
            console.log(data);
            @scope.myLazyLoadedData = data;  // async initialization
        });

ADDITION:

the following jsfiddle http://jsfiddle.net/jeromerg/43F28/2/ reproduces your example, by simulating the $http call with $timeout + $q. The example shows that everything is fine! If you still can't get the expected behavior, can you please extend the jsfiddle example and explain what you exactly expect? So that, we could better understand what is going on...

REMARK:

If you want to prevent displaying your view or a part of it before end of the $http call, then you can add ng-if="callFinished" attribute to the elements you want to hide in your template. And set the scope flag callFinished in the callback located in the controller as following:

helpdeskPriority.get().then(function { 
    $scope.callFinished = true; 
});

If you want to stay in the previous view until the end of $http call, and then change to this view, then you should make the $http call from within the previous view and perform the view change in the $http.success() callback there. Alternative: you can use the resolve property of the route provider as described here: Delaying AngularJS route change until model loaded to prevent flicker. But once the controller function of the new view has been called, I don't think it is possible to keep previous view displayed.

Community
  • 1
  • 1
jeromerg
  • 2,997
  • 2
  • 26
  • 36
  • 1
    No, `$timeout()` runs the delayed function inside `$scope.$apply()`, which triggers an Angular `$digest` cycle. That is not the problem here. – GregL Apr 10 '14 at 12:22
  • That's what I say: everything is fine concerning digest cycle. So I suspect that the bound variables are not set within the then() callback or are not defined in the scope, as suggested by the code provided by Pradeep Jaiswar, which doesn't show where the scope variables are set. – jeromerg Apr 10 '14 at 14:20
  • 1
    This is nothing to do with scope variables. The question was about how the `resolve` property of the [route configuration object](http://docs.angularjs.org/api/ngRoute/provider/$routeProvider) works. All it does is effectively allow you to delay running a controller for a route until some promises have resolved, and then inject the resolved value of those promises as a dependency to the controller. Whether you set any scope properties based on the values of those dependencies is a separate concern and is not the problem in this question. – GregL Apr 11 '14 at 03:01