简体   繁体   中英

Wait for loading of factory before resolve

I have code like this:

meow.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
    $routeProvider
    .when('/page', {
        templateUrl: 'application/partials/page.html',
        controller: 'index',
        resolve: {'page': ['$resolve', function($resolve) {return $resolve.page();}]}
    })
    .when('/page2', {
        templateUrl: 'application/partials/page2.html',
        controller: 'index',
        resolve: {'page2': ['$resolve', function($resolve) {return $resolve.page2();}]}
    })
    ...
    .otherwise({
        redirectTo: '/error'
    });
}]);
meow.factory('$resolve', ['$q', '$user', function($q, $user) {
    return {
        page: function() {
            var deferred = $q.defer();

            if ($user.logged()) {
                $http.get('/json/page')
                .success(function(data, status, headers, config) {
                    deferred.resolve();
                })
                .error(function(data, status, headers, config) {
                    deferred.reject();
                });
            } else {
                deferred.reject();
            }

            return deferred.promise;
        }
        page2:...
        page3:...
        ...
    }
}]);

As you can see there is check of user access in $resolve factory: $user.logged() , but $user is async and on first load it cause problems with access.

The question is how to make all my resolves wait for $user ?
I have $user.q() function which giving promise, but how to inject it to my code for all resolves? Or maybe some other solution with $routeChangeStart or $locationChangeStart events? Or should I just insert $user.q().then(...) in every resolve?

Update 1:
My user code:

meow.factory('$user', ['$q', '$http', function($q, $http) {
    var id = null;
    var accesslevel = 0;

    function update() {
        var deferred = $q.defer();

        $http.get('/json/user')
        .success(function(data, status, headers, config) {
            if (data.logged) {
                id = data.id;
                accesslevel = data.accesslevel;
            } else {
                id = null;
                accesslevel = 0;
            }
            deferred.resolve();
        })
        .error(function(data, status, headers, config) {
            deferred.reject();
        });

        return deferred.promise;
    }

    var q = update();

    return {
        logged: function() { return (id) ? true : false; },
        id: function() { return id; },
        accesslevel: function() { return accesslevel; },
        reset: function() {
            id = null;
            accesslevel = 0;
        },
        update: function() { return q = update(); },

        q: function() { return q; }
    };
}]);

Not controller should wait for $user.q() , resolve should. When I tryed to make it as additional resolve in $routeProvider , page resolve trying to load /json/page , but should not until $user.q() resolved and $user.logged() = true .

So the only way is to add

    page: function() {
        var deferred = $q.defer();

        $user.q().then(function() {
            if ($user.logged()) {
                $http.get('/json/page')
                .success(function(data, status, headers, config) {
                    deferred.resolve();
                })
                .error(function(data, status, headers, config) {
                    deferred.reject();
                });
            } else {
                deferred.reject();
            }
        });

        return deferred.promise;
    }

to each resolve?

The way you would normally approach dependencies like this would be to make user its own resolve and then make other resolve(s) depend on it, like so:

resolve: {
  user: function($user) {
    return $user.q();
  },
  somethingElse: function(user, $otherService) {
    // Whatever else
  }
}

This is kind of covered in UI Router wiki .

$user itself could be a promise that resolve to all service methods or you could resolve each service individually.

Usage

$user.then(function(userService) {
    userService.logged();
});

Resolution

var userDeferred= $q.defer();
userDeferred.resolve({
    logged: function() {
        return false;
    }
});
return userDeferred.promise;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM