Как избежать двух одинаковых запросов $ http.get - PullRequest
1 голос
/ 23 июня 2019

В angularJS, при одном вызове при получении ответа службы требуется доступ к значению json на нескольких контроллерах, но на одной странице

У меня есть два файла js контроллера, и оба контроллера вызываются на одной и той же странице, когда я вызывал службу this.getNavigationMenuDetails в первом файле controller.js, а также вызывался в файле controller2.js. без функции тайм-аута я хочу получить доступ к тому же ответу, который я получаю из службы this.getNavigationMenuDetails в controller2.js. Но так получилось, что сервис звонил дважды на страницу. Я не хочу вызывать один и тот же сервис дважды на странице. Когда 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 голосов
/ 24 июня 2019

Вы можете сделать это следующим образом.

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 в сервисе и вызовет сервисный метод для получения данных.первый вызов сделает переменную обслуживания 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()
}]);

При таком подходе вы можете обновлять данные в режиме реального времени доразные контроллеры не имеют несколько одинаковых запросов к серверу.

0 голосов
/ 23 июня 2019

Служба работала бы лучше, если бы она кэшировала обещание HTTP вместо значения:

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 для данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...