AngularJS Double HTTP请求,这是一个很好的解决方案还是我做错了什么?

时间:2017-01-12 08:55:33

标签: javascript angularjs q

结构

我有两个控制器和一个型号。

  1. 处理订单处理的一个步骤的订单控制器
  2. 订单导航控制器,仅处理订单的导航
  3. 处理订单所有数据的订单模型。
  4. 所有信息都存储在订单对象中,具体取决于您选择的捆绑包,您会收到配置该捆绑包的选项卡。

    在浏览订单的不同步骤时,导航控制器始终在执行其工作,订单控制器可以更改您当前所在的特定配置步骤所需的不同控制器。

    方案

    当加载第一个状态时,订单控制器正在初始化并且导航控制器正在初始化。两者都调用" OrderModel.getOrder()"方法,这是一个http调用的承诺。

    如果两个控制器都在初始化并且承诺未解决,那么它会导致对api的双重请求,我认为这有点过分。

    解决方案

    我在$ q库周围创建了一个包装器,它添加了一个独特的新方法。

    唯一的方法是将promise存入模型,如果promise不存在但它创建了一个新的promise,否则它返回尚未解析的promise。这可以防止多次http调用。

    问题

    因为这个解决方案看起来如此简单直接,我觉得我做错了什么,你们对这个结构/解决方案有何看法?

    示例代码:

    控制器getOrder方法:

    /**
         * @name getOrders
         * @param force
         * @description
         * Get the given order
         */
        function getOrder (id, force) {
            return $q(
                function (resolve, reject) {
                    Orders.getOrder(id, force).then(
                        function (order) {
                            vm.order = order;
                            resolve(order);
                        },
                        reject
                    );
                }
            );
        }
    

    模型getOrder方法:

    function getOrder (id, force) {
            var url = AppConfig.ApiUrl + '/order/' + id;
            var promiseUrl = url + '-force-' + force;
    
            return $qPromise.unique(promiseUrl, function (resolve, reject) {
                if (!force && model.orders[id]) {
                    return resolve(model.orders[id]);
                }
    
                $http.get(url, { bearer: true }).then(
                    function (response) {
                        model.orders[id] = response.data.data;
                        resolve(model.orders[id]);
                    },
                    reject
                );
            });
        }
    

    $ q包装器     (function(){

    angular.module('app').factory('$qPromise', qWrapper);
    
    qWrapper.$inject = ['$q'];
    
    /**
     * @name QWrapper
     * @param $q
     * @returns {*}
     * @description
     * Wrapper arround $q to add the unique method.
     */
    function qWrapper($q) {
        var model = {
            promises: {}
        };
    
        $q.unique = uniquePromise;
    
        return $q;
    
        /**
         * @name uniquePromise
         * @param id
         * @param cb
         * @description
         * Promise wrapper for preventing multiple calls for the same data.
         * @returns {*}
         */
        function uniquePromise (id, cb) {
            if (model.promises[id]) {
                return model.promises[id];
            }
    
            var promise = model.promises[id] = $q(cb);
            promise.catch(console.warn);
    
            $q.when(
                promise,
                function () { delete model.promises[id];  },
                function () { delete model.promises[id];  }
            );
    
            return promise;
        }
    }
    
    })();
    

1 个答案:

答案 0 :(得分:0)

我曾经面临一个场景,我必须同时进行两次http调用,因为两个http调用都给了我特定的json。所以我必须这样做,

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

app.controller('contactController',function($scope,$http,$q)
{
	
	var promise1=$http.get("https://jsonplaceholder.typicode.com/posts/1");
	var promise2=$http.get("https://jsonplaceholder.typicode.com/users/1");
$q.all([promise1, promise2]).then(function(data){ 
	$scope.first=data[0];
	$scope.second=data[1];
    console.log("------FIRST HTTP RESPONSE_____");
	console.log(JSON.stringify($scope.first));
      console.log("------SECOND HTTP RESPONSE_____");

	console.log(JSON.stringify($scope.second));
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>

<body ng-app="myapp" ng-controller="contactController">
  </body>

这实际上有效。 $ scope.first将给出第一个http调用的结果,$ scope.second给出第二个http调用的结果。

我不确定它是否符合您的需要,但我只是分享了我所知道的。也许一些线索可以提供帮助。