第一个AngularJS决定不起作用

时间:2014-07-25 14:06:01

标签: javascript angularjs

我第一次访问具有解决方案的路径时,不会发送对象请求。访问该页面的唯一方法是确保URL栏中的路径正确(键入或单击链接)并刷新页面而不缓存(在Firefox中按ctrl + shift + r或在Chrome中按ctrl + F5)。

我访问后第一次链接就可以了。

app.config(['$stateProvider', function($stateProvider){

  $stateProvider.state('users', {
    templateUrl: '/app/Users/templates/users.html',
    controller: 'Users',
    resolve: {
      'users': function(Objects, $stateParams){
        return Objects.getUsers();
      }
    },
    url: '^/users'
  });

  $stateProvider.state('user', {
    templateUrl: '/app/Users/templates/user.html',
    controller: 'User',
    resolve: {
      'user': function(Objects, $stateParams){
        return Objects.getUser($stateParams.id);
      }
    },
    url: '^/users/:id/'
  });
}]);

app.factory('Objects', ['$http', '$q', function($http, $q){
  /* Retrieve objects once */
  var _cache = {};

  function cache(key, promiseGetterFn) {
    if (key in _cache) {
      return _cache[key];
    }
    else {
      var promise = promiseGetterFn();
      _cache[key] = promise;
      return promise;
    }
  }
  return {
    unsetKey: function(key){
      delete _cache[key];
    },
    getUsers: function() {
      return cache('users', function () {
        var deferred = $q.defer();
        $http.get(HOST + '/api/v1.0/users/all').then(
          function (result) {
            deferred.resolve(result);
          });
        return deferred.promise;
      });
    },
    /*
    getUsers: function(){
      return cache('users', function(){
        return $http.get(HOST + '/api/v1.0/users/all').success(
          function(data, status, headers, config){
            return data.users;
          }
        );
      });
    },
    */
/*
    getUsers: function(){
      return cache('users', function(){
        var deferred = $q.defer();
        return $http.get(HOST + '/api/v1.0/users/all').then(
          function(result){
            deferred.resolve(result.data.users);
          },
          function(status){
            deferred.reject(status);
          }
        );
        return deferred.promise;
      });
    },
*/
    getUser: function(id){
      return cache('user_' + id, function(){
        var deferred = $q.defer();
        return $http.get(HOST + '/api/v1.0/user/' + id).then(
          function(result){
            deferred.resolve(result.data.user);
          },
          function(status){
            deferred.reject(status);
          }
        );
        return deferred.promise;
      });
    },
  };
}]);

app.run(['$rootScope', '$location', 'LocalService', function($rootScope, $location, LocalService){

  $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
    if (!toState.publicAccess && !LocalService.get('loggedIn')){
      /* Store the route they were trying to access */
      LocalService.set('next', $location.path());

      $location.path('/login');
    }
  });
}]);

登录代码后重定向

app.factory('AuthInterceptor', ['$q', '$injector', '$location', 'LocalService', function($q, $injector, $location, LocalService){
  /* Send Authorization in the header of each http request if there is a token */
  return {
    request: function(config){
      if (LocalService.get('token')){
        /* Using btoa to do Base64 */
        /* LocalService.password is only used on login to get token and will be empty ('') when using the token */
        config.headers.Authorization = 'Basic ' + btoa(LocalService.get('token') + ':' + LocalService.get('password'));
      }
      return config;
    },
    responseError: function(response){
      if(response.status === 401 || response.status === 403){
        /* Log the user out */
        LocalService.unset('loggedIn');
        LocalService.unset('token');
        LocalService.unset('user');
        $location.path('/login');
      }
      return $q.reject(response);
    }
  };
}]);

app.config(['$httpProvider', function($httpProvider){
  $httpProvider.interceptors.push('AuthInterceptor');
}]);

app.run(['$rootScope', '$location', 'LocalService', function($rootScope, $location, LocalService){

  $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
    if (!toState.publicAccess && !LocalService.get('loggedIn')){
      /* Store the route they were trying to access */
      LocalService.set('next', $location.path());

      $location.path('/login');
    }
  });
}]);

app.controller('Login', ['$scope', '$http', '$location', 'growl', 'LocalService',
  function($scope, $http, $location, growl, LocalService){
    $scope.email = '';
    $scope.password = '';

    $scope.submitLogin = function submitLogin(){
      LocalService.set('token', $scope.email);
      LocalService.set('password', $scope.password);
      $http.get(HOST + '/api/v1.0/token').
        success(function(data, status, headers, config) {
          LocalService.set('token', data.token);
          LocalService.set('loggedIn', true);
          LocalService.set('password', '');
          /* Set current user */
          $http.get(HOST + '/api/v1.0/authenticate').then(function(result) {
            LocalService.set('user', JSON.stringify(result.data));
            if (LocalService.get('next')){
              var next = LocalService.get('next');
              LocalService.unset('next');
              console.log(next);
              $location.path(next);
            }
            else{
              $location.path('/');
            }
          });
        }
      ).
      error(function(data, status, headers, config) {
          /* invalid credentials growl */
          growl.addErrorMessage('Invalid username or password.');
        }
      );
    };
  }
]);

3 个答案:

答案 0 :(得分:0)

我首先想到的是解析的对象只能在硬加载时解析。一旦从index.html实例化了应用程序,部分视图可能没有注册对象是promises。我会尝试从工厂(api)实际承诺返回对象。现在我从未见过像你这样的承诺,但我没有看到任何'deferred.resolve'或'deffered.reject'。例如:

 return {
    getBundles: function(){
      return cache('bundles', function(){
        var deffered = $q.defer
        return $http.get(HOST + '/api/v1.0/bundles/all').success(
          function(data, status, headers, config){
            deferred.resolve(data.bundles);
          }.error(function(status){
            deferred.reject(status);
        )};
        return deferred.promise;
      });
    },
  }

在执行此操作时,我还建议您在将对象绑定到视图之前将对象返回到javascript对象。这将在控制器中完成,并将“束”注入控制器。

var thisBundle = bundles.data.bundles;
thisBundle.then(function(data){
    $scope.bundles = data;
});

我发现的另一个解决方案是在路由中包含所有项目。试试这个:

resolve: {
        'allProducts' : function(){
            var theResolvePromise = $q.defer();
            theResolvePromise.resolve({
                bundles: ['Objects', function(Objects){
                  return Objects.getBundles();
                }],
                products: ['Objects', function(Objects){
                  return Objects.getProducts();
                }],
                technologies: ['Objects', function(Objects){
                   return Objects.getTechnologies();
                }],
                deliveryCategories: ['Objects', function(Objects){
                  return Objects.getDeliveryCategories();
                }],
             });
             return theResolvePromise.promise;
         };
      }
    }).

然后您将在控制器中访问此参数并传递参数。 取自:http://www.undefinednull.com/2014/02/17/resolve-in-angularjs-routes-explained-as-story/

希望这有帮助,

帕特里克

答案 1 :(得分:0)

试试这个。我没有测试它,所以它可能不完美,但也许它会帮助你找到正确的方向。

app.factory('Objects', ['$http', function($http){
  var _cache = {};

  function cache(key, getterFn) {
    if (_cache[key] == null) {
      _cache[key] = getterFn();
      _cache[key].then(function (result) {
          _cache[key] = result;
      });
    }

    return _cache[key];
  }

  return {
    unsetKey: function(key){
      delete _cache[key];
    },
    getUsers: function() {
      return cache('users', function () {
        return $http.get(HOST + '/api/v1.0/users/all');
      });
    },
    getUser: function(id){
      return cache('user_' + id, function() {
        return $http.get(HOST + '/api/v1.0/user/' + id).then(function (result) {
          return result.data.user;
        });
      });
    },
  };
}]);

$http.get返回一个在请求完成时解析的promise。从.then()函数返回值会将该值弹出到链中的下一个.then()。 UI-Router解析后会自动解包承诺。如果给出其他任何东西,它只会返回它。承诺不会自动解开Angular 1.2+,因此当您在缓存中工作时,您需要自己打开它。

答案 2 :(得分:0)

你的问题是2部分。

1)为什么我的第一个决心不解决状态的决心?

您第一次返回"承诺履行履行数据的承诺"。这就像一个链式的承诺。如果您返回了获取数据的承诺,则需要一个额外的$摘要周期来解决此问题。 $ http.get()返回一个promise。

In AngularJS the results of promise resolution are propagated asynchronously, inside a $digest cycle. So, callbacks registered with then() will only be called upon entering a $digest cycle.

同时检查出来

Angular JS: Chaining promises and the digest cycle

2)你可以改变什么来解决这个问题?

你可以做两件事    只需返回$ http.get(),因为这本身就是一个承诺。    为什么要缓存一个promise对象?您应该缓存实际数据。    使用$ resource和$ http,您可以传递{cache:true},结果将被缓存。或者,如果你想控制你可能想要使用$ cacheFactory。在这种情况下,您可以将实际结果放在缓存中,而不是promise对象。