Question

I'm trying to create app with deferred services - service need to perform async operation before it can be usable by controllers.

according to docs i should load any deferred data inside object passed to when() function:

resolve - {Object.<string, function>=} - 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.

but i can't force it to work.

app:

...
var loaded = false;
var deferData = {
  dfr: ['$rootScope', 'service', function($rootScope, service) {
      if (!loaded) {
        loaded = true;
        return service.loadData();
      }
    }
  ]
};
...
$routeProvider.when('/main', {
  templateUrl: './main.html',
  controller: 'mainCtrl',
  resolve: deferData
});

// default
$routeProvider.otherwise({
  redirectTo: '/main',
  resolve: deferData
});
...

service:

app.factory('service', ['$q',

function($q) {
  var s = {
    loadData: function() {
      var d = $q.defer();
      console.log('starting defer');
      setTimeout(function() {
        console.log('defer resolve');
        d.resolve('timeout');
      }, 2500);
      return d.promise;
    }
  };
  return s;
}

]);

this code sholud output (run, load defers, instantiate controller):

app run
starting defer
defer resolve
controller  init

but it output:

app run
starting defer
controller  init
defer resolve

link to plunker: http://plnkr.co/edit/k2D2taxAhSJkt5O174aw?p=preview

what i'm doing wrong? maybe i should resolve all my defers in .run(function(){ ... })? how to force router to wait until all defers resolved?

P.S. in my project i've got several services. some of them stores their settings in async storage, some of them need to be initialized after couple of http queries. i'm trying to prepare all my services with $q.all([ srv1.load(), srv2.load(), ... ]) and pass that final promise to resolove in router configuration.

Was it helpful?

Solution

resolve - {Object.=} - An optional map of dependencies which should be injected into the controller.

Therefore, to use resolve correctly, you should something like the following in your MainCtrl:

function MainCtrl(..., deferData) {
    ...
}

And the route should be:

$routeProvider.when('/main', {
    templateUrl: './main.html',
    controller: 'mainCtrl',
    resolve: {
        deferData: deferData
    }
});

Update:

The problem is you have two resolves in your $routeProvider call. Once you remove the one in the default route, your code should work as expect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top