如何避免两个相同的$ http.get请求

时间:2019-06-23 17:34:02

标签: angularjs

在angularJS中,只需调用一次,当获得服务响应时,需要在多个控制器中但在同一页面中访问该json值

我有两个控制器js文件,当我在第一个controller.js中调用服务“ this.getNavigationMenuDetails”以及在controller2.js文件中调用时,两个控制器在同一页面中调用。没有超时功能,我想访问从controller2.js中的“ this.getNavigationMenuDetails”服务获得的响应。但是碰巧该服务在页面中调用了两次。我不想在一个页面中两次调用相同的服务。 当js加载时,这两个控制器都在同一层中被调用,然后从服务获取响应,因此响应后第二个controller2.js文件代码不会执行。如何解决此问题,以便只有一个呼叫我可以获取响应并也可以在controller2.js中访问此响应。

controler1.js

var app = angular.module("navApp", []);

app.controller("navCtrl", ['$scope', 'topNavService', '$window', function ($scope, $timeout, topNavService, $window) {

    $scope.menuItemInfo = {};

    /*Navigation Menu new Code */
    $scope.getNavigationDetails = function () {
        topNavService.getNavigationMenuDetails().then(function (result) {
            $scope.menuItemInfo = result;
            angular.forEach($scope.menuItemInfo.items, function (val, key) {
                if (val.menuTitle === 
                        $window.sessionStorage.getItem('selectedNavMenu')) {
                    if ($scope.menuItemInfo.items[key].isEnabled) {
                        $scope.menuItemInfo.items[key].isActive = 'highlighted';
                    } else {
                        $window.sessionStorage.removeItem('selectedNavMenu');
                    }
                }
                if (val.menuTitle === 'Find a Fair' && !val.hasSubMenu) {
                    $scope.menuItemInfo.items[key].redirectTo = appConfig.findafairpageurl;
                }
            });
        });
    };
    $scope.init = function () {
        if ($window.location.pathname.indexOf('all-my-fairs.html') > 0) {
            if (angular.isDefined($cookies.get('cpt_bookfair'))) {
                $cookies.remove('cpt_bookfair', {
                    path: '/'
                });
            }
        }
        $scope.getNavigationDetails();
        $scope.callOnLoad();
    };

    $scope.init();
}]);
app.service('topNavService', ['$http', '$timeout', '$q'function ($http, $timeout, $q) {

    var menuInfo;
    this.getNavigationMenuDetails = function () {
        if (!menuInfo) {
            // If menu is undefined or null populate it from the backend
            return $http.get("/etc/designs/scholastic/bookfairs/jcr:content/page/header-ipar/header/c-bar.getMenuDetails.html?id=" + Math.random()).then(function (response) {
                menuInfo = response.data;
                return menuInfo;
            });
        } else {
            // Otherwise return the cached version
            return $q.when(menuInfo);
        }
    }
}]);

Controller2.js

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

app.controller('bookResourceCtrl', ['topNavService', '$scope', function (topNavService, $scope) {
    $scope.topInfo = '';

    topNavService.getNavigationMenuDetails.then(function success() {
        $scope.productId = $scope.topInfo.isLoggedin;
        $scope.linkParam = '?productId=' + $scope.productId;
    }, function failure() {
        console.error("something bad happened");
    });
}]);

2 个答案:

答案 0 :(得分:0)

如果该服务缓存了HTTP Promise而不是值,那么它将更好地工作:

app.service('topNavService', function ($http) {

    var menuInfoPromise;
    this.getNavigationMenuDetails = function () {
        if (!menuInfoPromise) {
            // If menu is undefined or null populate it from the backend
            menuInfoPromise =  $http.get(url);
        };
        return menuInfoPromise;
    };

});

缓存值的错误方法引入了竞争条件。如果第二个控制器在数据从服务器到达之前调用,则服务将为数据发送第二个XHR。

答案 1 :(得分:0)

您可以通过以下方法进行操作。

Service.js

app.service('topNavService', function($http) {

  var menuInfoPromise;
  var observerList = [];
  var inProgress = false;

  this.addObserver(callback) {
    if (callback) observerList.push(callback);
  }

  this.notifyObserver() {
    observerList.forEach(callback) {
      callback();
    }
  }

  this.getNavigationMenuDetails = function() {
    if (!menuInfoPromise && !inProgress) {
      inProgress = true;
      // If menu is undefined or null populate it from the backend
      menuInfoPromise = $http.get(url);
      this.notifyObserver();
    };
    return menuInfoPromise;
  };
});

您必须在使用中的功能,才能在列表中添加控制器的功能。然后每个控制器将在服务上注册其get函数并调用service方法以获取数据。第一次调用将使服务变量inProgress为true。因此它将阻止多个服务器的请求。然后,当有数据可供使用时,它将调用其notifyObserver函数,以通过调用所有函数向所有控制器发送消息。

控制器1

app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
  service.addObserver('getData1'); //name of your controller function

  $scope.getData1() {
    service.getNavigationMenuDetails.then(function success() {
      $scope.productId = $scope.topInfo.isLoggedin;
      $scope.linkParam = '?productId=' + $scope.productId;
    }, function failure() {
      console.error("something bad happened");
    });
  }
  $scope.getData1()
}]);

控制器2

app.controller('ctrl1', ['service', '$scope', function(service, $scope) {
  service.addObserver('getData2'); //name of your controller function

  $scope.getData2() {
    service.getNavigationMenuDetails.then(function success() {
      $scope.productId = $scope.topInfo.isLoggedin;
      $scope.linkParam = '?productId=' + $scope.productId;
    }, function failure() {
      console.error("something bad happened");
    });
  }

  $scope.getData2()
}]);

使用这种方法,您可以实时将数据更新到不同的控制器,而无需对服务器有多个相同的请求。