在Angular中防止多个$ http请求。有没有更好的办法? [英] Preventing multiple $http requests in Angular. Is there a better way?

查看:80
本文介绍了在Angular中防止多个$ http请求。有没有更好的办法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我构建了一个通过$ http返回资源的复杂方法。



该方法返回一个promise,然后检查我的本地缓存是否存在资源。如果是,它将返回缓存的资源,如果不是,它将发出$ http请求。在缓存资源之后这很好用,但是我在加载时触及此方法的应用程序中有多个函数,并且每个函数都会发出http请求,因为资源尚未返回并缓存。 / p>

我想出了一个简单的检查来解决这个问题,但我觉得应该有更好的方法。我添加了一个布尔值,如果方法正在获取资源,则设置为true,如果是,我使用半秒超时解析方法,以给予请求时间解决。代码如下。



那么,有更好的方法吗?

  var schools = []; 
var loadingSchools = false;

函数getAllSchools(forceUpdate){
返回$ q(函数(解析,拒绝){
if(loadingSchools)resolve($ timeout(getAllSchools,500));

else {

loadingSchools = true;

if(schools.length&&!forceUpdate){
loadingSchools = false;
解决(学校);
返回;
}

console.log('$ http:获取所有学校 - schoolService.js');

$ http.get(API_PATH +'schools_GetAll',{cache:true})
.success(函数(结果){
schools = result;
loadingSchools = false;
resolve(学校);
})
.error(函数(错误){
schools = [];
loadingSchools = false;
拒绝(错误);
});
}
});
}


解决方案

首先,我不喜欢我认为有必要将 HttpPromise 包装到另一个承诺中。使用成功/错误方法已弃用,您应该完全依赖 then()方法,并处理 HttpPromise 只是一个普通的承诺。



为了确保请求只发送一次,你实际上可以跟踪第一个<您创建的code> HttpPromise ,并且在该函数的后续调用中,返回相同的承诺。



这是一项服务,接受API端点作为参数,并确保只向该API发送一个请求。

  app.factory(' $ httpOnce',['$ http','$ cacheFactory',
函数($ http,$ cacheFactory){
var cache = $ cacheFactory('$ httpOnce');

返回函数$ httpOnce(url,options){
return cache.get(url)|| cache.put(url,$ http.get(url,options)
.then(func) (响应){
return response.data;
}));
};
}
]);

用法

 函数日志(数据){
console.log(data);
}

//发出HTTP请求
$ httpOnce('https://api.github.com/')。then(log);
//不发出HTTP请求,返回与上面相同的承诺
$ httpOnce('https://api.github.com/')。then(log);

// ... ...
// HTTP请求在某处完成,上面的两个承诺都解决了
// ... ...

setTimeout(function( ){
//立即解决
$ httpOnce('https://api.github.com/')。then(log);
},5000);

这是演示。您可以在开发工具中看到只发出一个请求。


I've built a somewhat complex method for returning a resources via $http.

The method returns a promise and then checks my local cache if the resources exists yet. If it does it will return the cached resources, if not it will make the $http request. This works great after the resource has been cached, but I have multiple functions through out the application that is hitting this method on load, and every one of them will make the http request because the resources hasn't been returned and cached yet.

I came up with a simple check that fixes this, but I feel like there should be a better way. I added a boolean that is set to true if the method is in the middle of getting the resource, and if it is I resolve the method with a half second timeout, to give the request time to resolve. Code is below.

So, is there a better way?

   var schools = [];
   var loadingSchools = false;

   function getAllSchools(forceUpdate) {
        return $q(function (resolve, reject) {
            if(loadingSchools) resolve($timeout(getAllSchools, 500));

            else{

                loadingSchools = true;

                if (schools.length && !forceUpdate) {
                    loadingSchools = false;
                    resolve(schools);
                    return;
                }

                console.log('$http: Getting All Schools - schoolService.js');

                $http.get(API_PATH + 'schools_GetAll', {cache:true})
                .success(function(result) {
                    schools = result;
                    loadingSchools = false;
                    resolve(schools);
                })
                .error(function(error) {
                    schools = [];
                    loadingSchools = false;
                    reject(error);
                });
            }
        });
    }

解决方案

First off, I don't think it's necessary to wrap the HttpPromise into another promise. With the success/error methods deprecated, you should rely solely on the then() method, and treat the HttpPromise as just a regular promise.

In order to make sure that the request is sent out only once, you can actually keep track of the first HttpPromise you create, and on subsequent calls of the function, return that same promise.

Here is a service which will accept an API endpoint as an argument, and ensure that only one request is sent out to that API.

app.factory('$httpOnce', [ '$http', '$cacheFactory',
  function ($http, $cacheFactory) {
    var cache = $cacheFactory('$httpOnce');

    return function $httpOnce(url, options) {
      return cache.get(url) || cache.put(url, $http.get(url, options)
        .then(function (response) {
          return response.data;
        }));
    };
  }
]);

Usage

function log(data) {
  console.log(data);
}

// issues an HTTP request
$httpOnce('https://api.github.com/').then(log);
// does not issue an HTTP request, returns the same promise as above
$httpOnce('https://api.github.com/').then(log);

// ...
// HTTP request completes somewhere, both promises above are resolved
// ...

setTimeout(function () {
  // immediately resolved
  $httpOnce('https://api.github.com/').then(log);
}, 5000);

Here is a demo. You can see in the dev tools that only one request is issued.

这篇关于在Angular中防止多个$ http请求。有没有更好的办法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆