2

我想了解如何为多个控制器设计单个 ajax 方法,这也会影响用户界面(例如,“加载”动画)。

想法是(没有承诺):

var myApp = angular.module('myApp', []);

myApp.controller('myCtrl',
    function myCtrl($scope, myFactory){
        $scope.loading = false;
        $scope.someStuff = myFactory.getStuff(params);
});

myApp.factory('myFactory', function(myService){
    return{
        getStuff: function(params){
            return myService.ajax(params);
        }
    }
});

myApp.service('myService', function($http) {
    this.ajax = function(params){
        // switch $scope.loading = true; 
        // make request
        // return $http result
        // switch $scope.loading = false; 
    };
});

据我所知,我需要使用 $scope 进行 UI 更改,并且应该将 ajax-method 用于自定义服务。Angularjs 中的服务不适用于 $scope,我不知道如何解决这个问题。

我认为,必须有一个带有承诺链的服务。怎么设计?

更新:我希望随着时间的推移文档会更加完整和清晰。但是角度用户社区已经很棒了。谢谢。

4

3 回答 3

0

在我的项目中,我定义了一个名为的服务appState,它具有(除其他外)方法:showGlobalSpinnerhideGlobalSpinner修改$rootScope.

基本上:

(…)
.factory('appState', ['$rootScope', function ($rootScope) {
    return {
        showGlobalSpinner: function () {
            ++$rootScope.loadingInProgress;
        },
        hideGlobalSpinner: function () {
            if ($rootScope.loadingInProgress > 0) {
                --$rootScope.loadingInProgress
            }
        }
    };
}]);

我接下来要做的是在需要的地方使用ng-show指令显示微调器:

<div class="spinner" ng-show="loadingInProgress"></div>

在每个 AJAX 之前我只是调用AppState.showGlobalSpinner(),在成功/错误之后我调用AppState.hideGlobalSpinner()

于 2013-09-04T12:40:27.090 回答
0

您可以将此方法添加到您的任何控制器:

.controller('HeaderCtrl',['$scope','httpRequestTracker', function($scope,httpRequestTracker) {
  $scope.hasPendingRequests = function () {
    return httpRequestTracker.hasPendingRequests();
  };
}]);


angular.module('services.httpRequestTracker', []);
angular.module('services.httpRequestTracker').factory('httpRequestTracker', ['$http', function($http){

  var httpRequestTracker = {};
  httpRequestTracker.hasPendingRequests = function() {
    return $http.pendingRequests.length > 0;
  };

  return httpRequestTracker;
}]);
于 2013-09-04T13:57:44.333 回答
0

您可以通过使用 HTTP 拦截器、一些事件和指令来尝试更通用的方法:

Javascript

app.factory('myHttpInterceptor', function($q, $rootScope) {
  return function(promise) {
    $rootScope.$broadcast('RequestStarted');

    var success = function(response) {    
      $rootScope.$broadcast('RequestFinished', true);
    };

    var error = function(response) {        
      $rootScope.$broadcast('RequestFinished', false);
      return $q.reject(response);
    };

    promise.then(success, error);
    return promise;
  }
})
.config(function($httpProvider) {
  $httpProvider.responseInterceptors.push('myHttpInterceptor');
})
.directive('loading', function() {
  return {
    restrict: 'E',
    transclude: true,
    template: '<div ng-show="visible" ng-transclude></div>',
    controller: function($scope) {
      $scope.visible = false;

      $scope.$on('RequestStarted', function() {
        $scope.visible = true;
      });

      $scope.$on('RequestFinished', function() {
        $scope.visible = false;
      });
    }
  };
});

HTML

...
<loading><h1>Loading...</h1></loading>
...

你可以在这里看到一个工作演示。

通过使用 HTTP 拦截器,您将能够跟踪$http服务($resource包括)在您的 Angular 应用程序中发出的每个 HTTP 请求,并相应地显示加载动画。

于 2013-09-04T17:05:15.250 回答