【问题标题】:How to avoid repeating http requests angularJS如何避免重复http请求angularJS
【发布时间】:2015-07-14 15:52:17
【问题描述】:

Angular 中有没有办法避免重复的 http 请求? 正如您在上面的代码中看到的那样,我正在调用以检索产品的详细信息。 事实上,这个调用与一个按钮相关联...... 我会避免重复调用。 如果我点击了详细的产品按钮,显然我不需要再次调用我的服务......正确的方法是加载一次信息然后显示和隐藏;但我不知道如何在 Angular 上进行管理。 (我也不想从头开始加载产品的详细信息,我只想根据用户的 clic 需求加载,但是一次)

$scope.seeInfo= function(id){

    $http.get('/shop/getDetailInfo/'+id).
        success(function(data, status) {
            $scope.info = data.detailinfo;
            if (data.detailinfo>0) $scope.showDetails=true;
            else $scope.showDetails=false;
        });

};

【问题讨论】:

    标签: javascript angularjs httprequest


    【解决方案1】:

    Angular $http 有一个内置的缓存功能,可能就是你所需要的

    https://docs.angularjs.org/api/ng/service/$http

    $scope.seeInfo= function(id){
    
        $http.get('/shop/getDetailInfo/'+id, {cache: true}).
            success(function(data, status) {
                $scope.info = data.detailinfo;
                if (data.detailinfo>0) $scope.showDetails=true;
                else $scope.showDetails=false;
            });
    
    };
    

    更新

    我看到您选择了“自己动手”解决方案,这通常比使用 Angular 提供的解决方案更容易出错。

    这里如何实现相同的:

    // access the $http cache 
    var httpCache = $cacheFactory('$http');
    // retrieve an element from cache
    var detailInfo = httpCache.get('/shop/getDetailInfo/' + id);
    // delete a cache element
    httpCache.remove('/shop/getDetailInfo/' + id);
    

    【讨论】:

    • 太棒了!这完美无缺,非常感谢。现在我想知道我的方法是否正确,因为我认为每次显示隐藏元素时都打电话不是很聪明..
    • 如果您想要“感觉”更好的东西,我建议您阅读 John's Papa 最佳实践 (github.com/johnpapa/angular-styleguide#data-services)
    【解决方案2】:

    您可以将用户请求的每个项目存储在工厂中,然后在进行 ajax 调用之前检查内容是否在工厂中。

       $scope.seeInfo= function(id){
            var detailinfo = someFactory.get(id); //get item data from factory if exist
            if (angular.isUndefined(detailinfo) || detailinfo === null) {
                $http.get('/shop/getDetailInfo/'+id).
                    success(function(data, status) {
                        someFactory.set(id, data); //set ajax data to factory
                        $scope.info = data.detailinfo;
                        if (data.detailinfo>0) $scope.showDetails=true;
                        else $scope.showDetails=false;
                    });
                }
            } else {
                $scope.info = detailinfo;
                if (detailinfo>0) $scope.showDetails=true;
                else $scope.showDetails=false;
            }
        };
    

    正如有人说你可以使用 $http 缓存,但我不知道它是如何工作的

    更新

    一个 someFactory 示例:

    .factory('someFactory', [function() {
    
        var storedItems = [];
    
        return {
            get: function(id) {
                return storedItems[id];
            },
            set: function(id, data) {
                storedItems[id] = data;
            }
        };
    
    }]);
    

    测试工厂:

    someFactory.set(12345, {"info":"Hello"});
    someFactory.set(2, "World");
    
    console.log(someFactory.get(12345).info); // returns Hello
    console.log(someFactory.get(2)); //returns World
    

    你可以存储字符串、对象......

    希望对你有帮助

    UPDATE2完整示例代码

    var someApp = angular.module("someApp", [])
    
    .controller('someCtrl', ['someFactory', function(someFactory) {
    
      someFactory.set(12345, {"info":"Hello"});
      someFactory.set(2, "World");
    
      console.log(someFactory.get(12345).info); // returns Hello
      console.log(someFactory.get(2)); //returns World
    
    }]).factory('someFactory', [function() {
    
        var storedItems = [];
    
        return {
            get: function(id) {
                return storedItems[id];
            },
            set: function(id, data) {
                storedItems[id] = data;
            }
        };
    
    }]);
    

    【讨论】:

    • 你的解决方案看起来很酷,但你能提供更多关于如何声明“someFactory”的信息吗?再次感谢
    • 您需要以某种方式将此工厂“附加”到您的控制器上,不是吗?我收到了一个错误,但我认为这是因为我错过了这部分......对不起!
    • 你需要注入它(someFactory)作为你的控制器的依赖,如 $scope 或 $http
    • @FrnndSgz 用完整的代码示例查看最新更新
    • 哦!感谢完整版。顺便说一句,Angular 提供的 $cacheFactory 是不是类似的东西? docs.angularjs.org/api/ng/service/$cacheFactory
    【解决方案3】:

    使用范围变量绑定第一次调用。

    $scope.wasCalled = false;
    $scope.seeInfo= function(id){
        if ( $scope.wasCalled == false ) {
        $http.get('/shop/getDetailInfo/'+id).
            success(function(data, status) {
                $scope.info = data.detailinfo;
                $scope.wasCalled = true;
            });
        }
    };
    

    它设置为成功,因此服务器错误代码将在 200 到 299 之间。 然后您可以根据$scope.wasCalled 变量在视图中设置ng-show


    这是考虑到不同 id 调用的实现。

    $scope.callIds = [];
    $scope.wasCalled = function(id){
    for ( var k = 0 ; k < $scope.callIds.length ; k++ ) 
        if ( $scope.callIds[k] == id ) 
            return true;
    return false;
    };
    $scope.addCalled = function(id){
        $scope.callIds.push(id);
    };
    $scope.seeInfo= function(id){
        if ( $scope.wasCalled(id) == false ) {
        $http.get('/shop/getDetailInfo/'+id).
            success(function(data, status) {
                $scope.info = data.detailinfo;
                $scope.addCalled(id);
            });
        }
    };
    

    检查指定的 id 是否被调用,如果没有,使用 $http 调用并将 id 添加到列表中。

    【讨论】:

    • 如果你需要用不同的 id 调用它怎么办?
    猜你喜欢
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    相关资源
    最近更新 更多