Angularjs中ajax的单一方法体系结构

Architecture of single method for ajax in Angularjs

本文关键字:方法 体系结构 单一 ajax Angularjs      更新时间:2023-09-26

我想了解如何为多个控制器设计单个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方法用于自定义服务。Angularjs中的服务不适用于$scope,我不知道如何解决这个问题。

我认为,必须有一个承诺链的服务。它是如何设计的?

Upd:我希望随着时间的推移,文档会更加完整和清晰。但棱角分明的用户群体已经很棒了。谢谢

在我的项目中,我定义了一个名为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()

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

.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;
}]);

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