一个通用广告脚本数据加载的容错
最基本的需求
写一个通用的广告脚本文件,传递不同的广告ID,加载对应的数据出来,上报数据,最后显示出来
最简单的做法
每个站点,直接请求广告地址,带上不同参数,例如这样:
1 2 3 4 5 6 7 8 | var script = document.createElement( "script" ); script.src = 'ad.com?id=id1&callback=cb' ; document.body.appendChild(script); function cb(param){ //do something new Image().src = "report.com?id=id1" ; } |
以上做法存在的问题:
- 每个站点都需要记住请求的地址,万一地址改了,全都要改
- 每个站点,都需要自己去写请求,以及回调
- 每个站点,都需要自己去上报数据
- 请求失败了,怎么办?
- 请求时间很长,怎么办?
站点的使用,更应该关心的是:
- 统一的接口
- 只需要传ID和回调函数
- 返回需要的数据进行渲染页面
- 错误、失败、上报、超时等不需要关心
我们可以这样做
1、统一处理请求
采用类
jQuery
的方式来进行jsonp
请求,增加超时和错误监控
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | //简易版jsonp ; var __GetScript = function (){ //发送请求(闭包) //param object json参数 //param.url 请求的地址 //param.data 请求的参数 //param.success 请求成功的回调 //param.error 请求失败的回调 function send(param){ //随机函数名字,类似jquery var random = "script" + Math.floor(Math.random() * 100000 + 100000); //计时器Id,用于超时abort var timeId = 0; //创建script脚本 var script = document.createElement( "script" ); script.type = "text/javascript" ; //绑定脚本错误事件 var onerror = script.onerror = function (){ //如果计时器是空,则表示请求成功了 if (!timeId) return false ; clearTimeout(timeId); //回调用户错误函数 param.error(); //移除script标签以及对应成功函数 document.body.removeChild(script); window.random = null ; }; //绑定全局回调成功函数 window[random] = function (){ if (!timeId) return false ; clearTimeout(timeId); //将jsonp的参数列表,返回给用户的回调函数 try { param.success.apply( null ,arguments); } catch (e){ //用户回调执行出错,执行错误函数 param.error(); } //移除script标签以及对应成功函数 document.body.removeChild(script); window.random = null ; } //超时则直接返回失败,这里设置了3秒 timeId = setTimeout( function (){ //触发onerror事件 onerror(); timeId = 0; },3000); //script的请求,一定是在最后 script.src = param.url + "?" + param.data + "&callback=" + random; document.body.appendChild(script); } //返回请求接口 return send; }(); //调用demo,这样看起来,就跟jquery的差不多了 __GetScript({ url : 'ad.com' , data : 'id=id1' , success : function (data){}, error : function (){} }); |
2、超时、请求失败
服务器挂了,服务器卡住了,那广告位总不能显示空白吧?
用户第一次访问,服务器就挂了(这种表示无奈),显示一个加载失败的提示文案或者图标之类的,统一在广告位加上一个标识来处理
用户第一次访问成功过,但之后第二次访问的时候才挂的,那么可以考虑使用上一次成功的数据来展示
2.1 每次请求成功,缓存成功数据,格式采用
json
格式,旧版使用json2
来支持
2.2 IE使用userData
,标准浏览器用localStorage
2.3 合并新请求的数据与旧的缓存数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | //拉取数据成功 function getDataSucc(data,pos,cb_list){ //移除正在请求的提示 $( ".adbase-ctn" ).css( "background" , "none" ); //获取本地缓存数据 var locData = getDataByLoc(pos); //合并与覆盖最新数据到本地中 locData = extendData(locData,data); //记录当前数据,JSON对应在旧浏览器需要用第三方库`json2` LocalData.set(pos,JSON.stringify(locData)); //回调给用户 for ( var i=0;i<cb_list.length;i++){ cb_list[i]( true ,locData); } } //获取本地缓存数据 function getDataByLoc(pos){ //LocalData对象是操作userData和localStorage var data = LocalData.get(pos); if (!data) return {}; //从缓存中读取的字符串,转成json对象 return JSON.parse(data); } //合并新旧数据 function extendData(oldData,newData){ for ( var key in newData){ //本地没有这个数据,合并 if (!oldData[key] || oldData[key].length < 1){ oldData[key] = newData[key]; continue ; } //本地跟新数据都有,合并 if ((oldData[key] && oldData[key].length) && (newData[key] && newData[key].length)){ oldData[key] = newData[key]; continue ; } //新数据没有,本地数据有,不合并 if ((oldData[key] && oldData[key].length) && (!newData[key] || newData[key].length < 1)){ continue ; } //本地没有,新数据也没有 if ((!newData[key] || newData[key].length < 1) && (!oldData[key] || oldData[key].length < 1)){ oldData[key] = []; } } return oldData; } |
3、其它收尾细节
处理完请求和缓存这两块主要的,还有一些细节需要考虑
- 在请求成功后,统一上报数据,该请求可以稍微往后,用
setTimeout
- 在有数据的情况下(可能只是部分),需要针对没有数据的广告位进行显示失败的提示,例如:
1 2 3 4 5 6 7 8 | //监测是否存在空数据的广告位 function checkNoDataCtn(){ //循环遍历容器是否有子元素 $( ".adbase-ctn" ).each( function (index,item){ if ($(item).contents().length < 1)$(item).css( "background" , "url(http://res.nie.netease.com/comm/js/nie/util/img/error.png) center center no-repeat" ); }); } |
- IE7的
userData
的key
只支持的规则和定义变量一致,不能带有类似,
,;
这种分隔符 - 低版本的IE浏览器,即使
script
请求失败了,也不会调用onerror
事件,统一采用超时机制就好了
PS:更多代码详情,请参考:adbase
手机阅读请扫描下方二维码:
__GetScript 这个函数,里面的success方法没起作用。
1
555
1
1
1
1
1
1
1
1
1
1
1
1
1
1
不错哦,赞一个,求认识,求回访 http://www.xevip.cn
555
555
文章很好~!赞 http://www.viplinger.cn
12345678

1
12345678

12345678

12345678

12345678

12345678

gyskureniqpnfpnlsiiq
12345678

12345678

12345678

12345678

12345678

555
文章很好~!赞 欢迎回访:www.3gwb.com
12345678

12345678

12345678

12345678

12345678

12345678

12345678

12345678

12345678

1

1

1

1

1
1
1
1
555
1
1
1
1
1

1

1
1
1
555
1
555
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1