0

I am trying to initialize my applications services before the controller starts running.

I would have thought that i could achieve this by resolving a promise-returning function first:

va.config(['$routeProvider', function($routeProvider) {
$routeProvider.
    when('/', {templateUrl: '../partials/home.php',   controller: 'VaCtrl',resolve: {
        pp: vac.loadData
    }});
}]);


var  vac = va.controller('VaCtrl',function($scope,$http,$q,packingProvider){
    console.dir(packingProvider.data[2]); 
});


vac.loadData = function($http,$timeout,$q,packingProvider){

   $http.post('../sys/core/fetchPacking.php').then(function(promise){
        packingProvider.data = promise.data;

    });

    var defer = $q.defer();
    $timeout(function(){
        defer.resolve();
    },2000);
    return defer.promise;
};

However, the controller is still loaded before the promise has beenr esolved, resulting in the console yelling

Cannot read property '2' of undefined

at me.

What am i doing wrong?

Edit:

Also, the controller seems to get invoked twice, first time with the undefined pacingProvider.data object, and 2 secons later with everything fine.

2 Answers 2

3

Instead of using the promise returned by $timeout, you could directly use the promise returned by $http.

Rewrite your loadData fn this way -

vac.loadData = function($http,$timeout,$q,packingProvider){

    var promise = $http.post('../sys/core/fetchPacking.php').then(function(promise){
        packingProvider.data = promise.data;
    });

    return promise;
};

Read the first line in the General Usage section here - $http promise

Also, resolve is a map of dependencies.

resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated.

Hence, Angular will automatically expose the map for injection. So, you can do this -

var vac = va.controller('VaCtrl', function($scope, pp){
  // 'pp' is the name of the value in the resolve map for $routeProvider.
  console.dir(pp[2]);
});
Sign up to request clarification or add additional context in comments.

6 Comments

If you jut want to use the value in the controller, it's even easier, as you can just inject the result to your controller. Edited the post to add this example. Can I edit your post in order to add the code example to the end?
Ya sure. Would like to see the example.
oh! Sorry for the typo.
Haha. Funny variable name. Anyway. Great addition, didn't know about this. How would I normally access pp? route.pp?
There is no other way I guess. Except for what he is doing, storing into a service and retrieving it. But I'd stick to the injection, for sure.
|
3

NOTE: although this will solve your problem, this answer is probably the right solution.

Services are always initialized before controllers. The problem, as you stated, is that your promise hasn't resulted yet. The best option for that is to stick to the promises.

Instead of exposing the data object, expose the promise and use it:

vac.loadData = function($http,$timeout,$q,packingProvider){
  packingProvider.data = $http.post('../sys/core/fetchPacking.php');
  return packingProvider.data;
};

And in your controller, always attached to the promise, after the first resolval, it will get resolved in the next tick:

var  vac = va.controller('VaCtrl',function($scope,$http,$q,packingProvider){
  packingProvider.data.then(function(value) {
    console.dir(value[2]);
  }); 
});

1 Comment

I don't think it is required to check promise in the controller. The $routeProvider will only enter the controller once promises defined in resolve run through.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.