REST服务返回204数据无更新

微信浏览器数据不更新

Angular调用自己做的REST后台,发现电脑浏览器正常,在手机微信浏览器等,数据接口死活不更新,无奈,晕死。一直以为是angular的缓存问题?ionic的缓存问题,微信浏览器的缓存问题?后来发现统统都不是。通过抓包发现,手机浏览器发出了正常的HTTP请求,但是返回的结果是204,no content,导致没有数据更新。这一点可能是手机浏览器处理的问题,由于是个长链接,在options请求返回204后,get请求仍然返回的是204。我是用loopback做得服务端,所以这里放到loopback教程里,可能是REST协议方面的bug。
教程索引:(持续更新)
loopback中文教程

皓眸大前端开发学习

转载请注明出处:http://www.haomou.net/2015/08/12/2015_loopback_rest/

微信浏览器问题出现

不只是微信浏览器,电脑浏览器有时也会出现这个问题,刚添加的数据,刷新页面发现没有?但是,开启F12浏览器控制台,开启disable cache,发现乖乖正常。这个问题的诡异之处是不好调试。开启控制台,就正常,不开启就没有数据更新。一开始一致以为是浏览器缓存问题,想了各种招数。比如添加meta:

1
2
3
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

发现不行。
后来在ionic中禁用view cache,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ionicConfigProvider.views.maxCache(0);
....
...
.state('tab.cake-design', {
url: '/design/:cakeId',
cache: false,
views: {
'tab-design': {
templateUrl: 'design.html',
controller: 'DesignCtrl'
}
}
})
...

发现都不行

难道是Angular的缓存

查了各种文档,发现angular发送http请求的确有缓存,有个cacheFactory
在Angular中,我们可以非常方便的进行AJAX请求。我们只需要注入$http,进行一个AJAX请求 – 然后我们就能得到一个promise对象,并可以很方便的调用其中的success或者error方法。例如下面的代码:

1
2
3
4
5
6
7
$http.get('/foo/bar' + itemId)
.success(function(data){
data;// {foo: 'bar'}
})
.error(function(data,status,headers,config){
//一些错误处理的代码
});

ok,现在你已经从后端得到了一些数据,那么然后呢?像上面例子中的这种数据似乎并不会频繁的发生变化,因此你会想为什么你的客户端需要重复进行同样的请求获取同样的数据呢 – 多么浪费时间消耗资源一件事情!好在我们可以使用缓存来为你节省时间和带宽,如下面的代码所示:

1
2
3
4
5
6
7
$http.get('/foo/bar' + itemId, {cache: true})
.success(function(data){
data; //{foo : 'bar'}
})
.error(function(data,status,headers,config){
//一些错误处理代码
});

非常好!现在,假如$http第一次想/foo/bar/123发出了一个GET请求,响应的结果会被存储在一个叫做$http的缓存中,这个缓存由Angular的$cacheFactory创建,并在Angular启动时会作为$http service的默认缓存。{cache: true}告诉$http service要在$http的默认缓存中缓存特定的请求响应结果。除此之外,你什么都不用做。任何针对/foo/bar/123的后续请求都会简单地使用这个缓存的结果。

如果你想要引用这个$http的默认缓存来获取其中的项目,移除其中的项目,清空缓存等等。你只需要在任何地方注入$cahcheFactory即可,然后我们就可以通过下面的代码来引用默认$http缓存:

1
var $httpDefaultCache = $cacheFactory.get('$http');

你也可以使用你进行GET请求的绝对路径来获取相应的请求相应结果:

1
var cacheDate = $httpDefaultCache.get('http://example.com/foo/bar/123'); // { foo : 'bar'}

你可以从缓存中移除项目:

1
$httpDefaultCache.remove('http://example.com/foo/bar/123');

或者清空整个缓存:

1
$httpDefaultCache.removeAll();

LRU 缓存

如果你不想要$http来存储每一次相应怎么办?这也很简单:你只需要将它设置为LRU缓存即可(Least Recently Used)。

1
2
3
4
5
6
7
8
9
var lruCache = $cacheFactory('lruCache',{ capacity : 10 });  

$http.get('/foo/bar/' + itemId, { cache: lruCache })
.success(function (data) {
data; // { foo: 'bar' }
})
.error(function (data, status, headers, config) {
// 一些错误处理代码
});

每个针对/foo/bar/:itemId请求的响应都会被缓存,但是在上面的代码中缓存次数只有十次。当发送第十一次请求时,最早一次的缓存会从缓存中被移除。这里的缓存按顺序包含着一个项目列表以便它在进行一次新的请求时知道应该移除哪一个旧的缓存项目。

设置一个默认缓存
正如前面的LRU的例子所示,你可以告诉$http请求使用一个自定义的缓存而不是$http默认缓存,但是如果你想要改变$http默认缓存怎么办?这也很简单:

1
$httpProvider.defaults.cache = $cacheFactory('myNewDefaultCache',{capacity: 100 });

$http现在就回使用myNewDefaultCache作为它的默认缓存。

高级缓存

如果你想使用缓存来改善用户体验,但是数据可能在一天或者几个小时之内就发生一次改变该怎么办?你可能想要确保你的缓存数据一天或者几个十分钟就清空一次。但是不幸的是,Angular中的$cacheFactory并没有提供这次额功能。

你可以使用setInterval()或者setTimeout()来进行一些修改,但是你可能并不想干这些事情。为了解决这个问题,我们可以使用一个叫做angular-cache的第三方模块。使用这个模块,你可以定期清理你的缓存。当设置一个缓存时你可以指定maxAge,它用来表明该缓存中某个项目的最长存续时间。或者你可以对整个缓存指定maxAge,它将运用在添加到该缓存中的所有项目之上。

不是angular的缓存

测试了一下,发现并没有什么卵用。不是angular的缓存引起的。在手机上调试,抓包吧。发现原来请求的REST接口返回的状态是204,no content。不晓得为什么,loopback做的rest服务返回的状态是204。好吧,我伤心了,我快乐了,发现了这个问题,就简单了。

解决方法就是在请求的接口url增加额外参数t值为当前时间的毫秒数,或者随机数,就可以了。记得自己直接这么做过,但是后台不知道为何又出现这个问题,特此记载一下烦心的问题。

谢谢!

转载请注明出处:http://www.haomou.net/2015/08/12/2015_loopback_rest/

有问题请留言。T_T 皓眸大前端开发学习 T_T