AngularJS load service then call controller and re

2019-02-02 06:01发布

My problem is that i need a service loaded before the controller get called and the template get rendered. http://jsfiddle.net/g75XQ/2/

Html:

<div ng-app="app" ng-controller="root">
    <h3>Do not render this before user has loaded</h3>            
    {{user}}
</div>
​

JavaScript:

angular.module('app', []).
factory('user',function($timeout,$q){
    var user = {};            
    $timeout(function(){//Simulate a request
        user.name = "Jossi";
    },1000);
    return user;
}).
controller('root',function($scope,user){

    alert("Do not alert before user has loaded");
    $scope.user = user;

});
​

6条回答
相关推荐>>
2楼-- · 2019-02-02 06:24

As I said in the comments, it would be a lot easier to handle an unloaded state in your controller, you can benefit from $q to make this very straightforward: http://jsfiddle.net/g/g75XQ/4/

if you want to make something in the controller when user is loaded: http://jsfiddle.net/g/g75XQ/6/

EDIT: To delay the route change until some data is loaded, look at this answer: Delaying AngularJS route change until model loaded to prevent flicker

查看更多
贼婆χ
3楼-- · 2019-02-02 06:25

even better than manually bootstrapping (which is not always a bad idea either).

angular.module('myApp', ['app.services'])
   .run(function(myservice) {
      //stuff here.
   });
查看更多
SAY GOODBYE
4楼-- · 2019-02-02 06:28

There are a few ways, some more advanced than others, but in your case ng-hide does the trick. See http://jsfiddle.net/roytruelove/g75XQ/3/

查看更多
Explosion°爆炸
5楼-- · 2019-02-02 06:35

You can use resolve in the .config $routeProvider. If a promise is returned (as it is here), the route won't load until it is resolved or rejected. Also, the return value will be available to injected into the controller (in this case Somert).

angular.module('somertApp')
  .config(function($routeProvider) {
    $routeProvider
      .when('/home/:userName', {
        /**/
        resolve: {
          Somert: function($q, $location, Somert) {
            var deferred = $q.defer();
            Somert.get(function(somertVal) {
              if (somertVal) {
                deferred.resolve(somertVal);
              } else {
                deferred.resolve();
                $location.path('/error/'); //or somehow handle not getting
              }
            });
            return deferred.promise;
          },
        },
      });
  });
查看更多
Viruses.
6楼-- · 2019-02-02 06:44

The correct way to achieve that is using resolve property on routes definition: see http://docs.angularjs.org/api/ngRoute.$routeProvider

then create and return a promise using the $q service; also use $http to make the request and on response, resolve the promise.

That way, when route is resolved and controller is loaded, the result of the promise will be already available and not flickering will happen.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-02-02 06:45

You can defer init of angular app using manual initialization, instead of auto init with ng-app attribute.

// define some service that has `$window` injected and read your data from it
angular.service('myService', ['$window', ($window) =>({   
      getData() {
          return $window.myData;
      }
}))    

const callService = (cb) => {
   $.ajax(...).success((data)=>{
         window.myData = data;
         cb(data)
   })
}

// init angular app 
angular.element(document).ready(function() {
       callService(function (data) {
          doSomething(data);
          angular.bootstrap(document);
       });
});

where callService is your function performing AJAX call and accepting success callback, which will init angular app.

Also check ngCloak directive, since it maybe everything you need.

Alternatively, when using ngRoute you can use resolve property, for that you can see @honkskillet answer

查看更多
登录 后发表回答