需求:在网站首页加了一个广告模态框,要求每天第一次访问时弹出,此后当天不再弹。
网站上线的当天晚上,大BOSS临时加的一个小需求,当时感觉没什么困难的,几分钟的事情,模态框和cookie操作都是封装好的工具方法,只要将广告图片加上,再存个弹出标识cookie,设置过期时间24小时就ok。然而,实际操作起来,效果却不理想。
我们项目用的是angularjs 1.3的框架,说这个问题之前,不得不提我做登录功能时,遇到的另一个cookie问题。当时操作cookie用的是$cookieStore。但是他好像不兼容IE8,当时用他来做登录功能时,发现页面不能跳转,一跳转页面cookie就会消失,在本页面即使刷新也能读取到cookie。
首先百度查了又查,有的说是IE8设置问题,有的说是用法问题,有的说是兼容问题,反正我都试了,最终只能归咎于兼容问题。同时可以肯定的,这应该是和cookie的作用域或是路径有关系,但是我又没法查看IE8下面cookie的详细信息,而$cookieStore又无法手动设置作用域和路径。这时,我想起以前用过用js封装过cookie工具方法,确定是可以兼容IE8的。于是我就直接拿过来用了,最后测试IE8,果然问题没了。此外我还多测了一下,利用js的方法,我不设置作用域,问题任然存在。
再次回到本问题,此次我用的仍是前面的用到的js方法,我信誓旦旦应该不存在什么问题的,但偏偏问题又来了。这次的情况是这样的,在本页面设置cookie后,跳转页面也能获取到,但是一刷新cookie我获取到的值就为空字符串。当时简直傻眼了,因为晚上还要上线,我前面还和经理保证过没问题的,结果又遇到坑了,我那个急啊,因为我原本没想当过会出问题的地方,居然又出了一个无脑的问题,搞的我一脸萌币。而且又急着上线,搞的我一点解决思路都没得;但是没法只能硬着头皮上了。
首先还是百度,百度上也有类似的问题,但是很少,而且都没有确切的回答(估计是因为问题太SB);终于,翻到了一个比较靠谱的回答,大概的意思是这样的:cookie域名设置必须要是域名,IP地址无效。靠,我顿时恍然大悟(此时我完全忘了以前的登录功能就是用IP做的),于是又用host文件映射IP和域名,最后一测,果然有效,我简直要笑了,不要这么轻松好不好~
于是,我兴冲冲的跑去跟经理汇报了,经理一听立刻就把网站发到了公测环境;然后经理一打开网站就看到了弹窗,然后刷新,弹窗又出来了,再然后就问我,这弹窗为什么还一直弹啊,我当时就猜到他会这么问了,然后就把网上的答案给他了,我说,因为cookie设置需要用具体的域名,ip设置无效,放到线上就好了(此时仍未发现问题)~见鬼了,当天晚上因为测试请假先走了,这个问题最后到上线都没人发现。
终于,网站上线了,我又兴冲冲打开线上的网站来验证,一打开,广告出来了,然后刷新,他 妹 的又出来了,我靠,当时我的脸顿时感到火辣辣的。但是没办法问题还在啊,我一边忍着不哭一边慌忙的再次找原因,但是经过这么一搞,我又一点思路都没了。
之后因为上线时已经是晚上9点30了,经理就过来跟我们说,网站上线了,大问题没有,但是那个弹窗还是老弹(当时真想钻地缝),今晚不早了就先下班吧~~~然后同事们就迅速的关机走人了。当时我真不想走的,因为真的是太尴尬了,但是留下来又不知道要搞到什么时候,关键是公司又没人了,好吧,先走吧,明天再说......于是,我也关机走人。
到家了,以前都是很兴奋的,搞不好还会先撸一把再睡,但是那天晚上终于没心情了,念念不忘刚才的问题,但是怎么也想不通。于是,我又打开电脑、打开google、打开线上的网站,打开控制台......然后让自己平静下,再次从头开始排查,首先我发现cookie设置是成功的,从google上看到cookie的过期时间、作用域和路径都没问题,于是排除cookie本身的问题。其次,是使用的工具方法,用的是以前的老方法,因此问题应该不在方法上。
最后,我发现,当我刷新页面时,cookie也跟着刷新;这地方就很奇怪了,因为cookie的过期时间是24小时,怎么可能一刷新页面,cookie就像刷新一样呢?幸好在家里人比较冷静,稍微思考下就想到一种可能性,那就是在前面的js中,可能在某些地方对cookie做了清除,有了这个想法,我马上进行了验证,果然在验证登录状态的方法中利用了清除cookie的操作,当初这么做是为了检测到未登录时,避免残留cookie对后面产生影响,就偷懒用了清空所有cookie,这就导致不登录时cookie永远都会先清后存。
总结:这是一个自己坑自己的故事,我想在实际开发中这类问题应该会经常遇到,只能更加细心一点,让自己少点坑!
附兼容IE的cookie操作方法:
var $tools= {
//清楚所有cookie,或清除指定名称的cookie
clearAll: function (me){
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
if (!!me){
if (me === $.trim(name)){
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
}
}else{
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
}
}
if(cookies.length > 0)
{
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
var domain = location.host.substr(location.host.indexOf('.'));
if (!!me){
if (me === $.trim(name)){
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" + domain;
}
}else {
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" + domain;
}
}
}
},
//保存cookie
setCookie: function (name, value, hour, domain){
if (!!domain && domain.indexOf('www.') != -1){
domain= domain.substring(4);
}
var curCookie = name + "=" + encodeURIComponent(value) +";";
if(0 != hour){
var date = new Date();
date.setTime(date.getTime() + hour * 3600 * 1000);
var expires = date.toGMTString();
curCookie += "expires=" + expires +";";
}
curCookie += "path=/";
if(""!=domain){
curCookie += ";domain="+domain;
}
document.cookie = curCookie;
},
//获得cookie
getCookie: function (name){
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1){
begin = dc.indexOf(prefix);
if (begin != 0) return "";
}else{
begin += 2;
}
var end = document.cookie.indexOf(";", begin);
if (end == -1){
end = dc.length;
}
return unescape(dc.substring(begin + prefix.length, end));
}
}