自己实现一个JsonP
在没有XMLHttpRequest lEvel2的时候,我们在使用Ajax的时候要实现客户端跨域就只能用jsonp。而jsonp的原理很简单,那就是利用了浏览器加载JavaScript和css等资源的时候是允许跨域加载的。 这也是以前黑客经常攻击我cms搭建网站的方式。莫名其妙让我的主页打开以后就跳到其他地方了。有的黑客直接给我写到首页代码里,有的黑客使用script脚本引入的方式。 jsonp的原理: 说出来很简单,那就是动态创建<script src="你ajax发起GET请求的地址"></script>这个DOM。 这样的话,浏览器就允许script标签请求跨域的内容,但是如何拿到服务端返回的内容并让浏览器端开发人员做点事情呢。 这里用到另一个技巧,很土的办法:那就是让服务端返回的内容就直接是一个函数调用的语法。 比如:服务端返回这样的内容-----> YourFunc({服务端要返回给客户的对象}){} Demo:YourFunc({"a":1,"b":2})
然后客户端需要提前动态在全局空间内注册一个函数,其名称为YourFunc(data){}. 这样当<script src="ajaxurl"></script>请求返回数据后,浏览器解析其中的内容,会自动执行YourFunc({a:1,b:2}), 这样就调用了你提前注册好的函数YourFunc(data){}; 你在全局空间中注册的函数可以这样写:YourFunc(rel){ 执行服务器结果处理的事情 } 我的JsonP封装: 我对Ajax请求的创建和执行进行了函数封装,以方便开发人员使用。ajax请求函数如下: 需要注意的是:在我的ajax函数使用时需要遵循一个约定,那就是服务端返回的数据约定为: { "success":true or false, "errormsg":your logic error, "data":your data when success,if failed put it null is ok. } //函数形参说明: //Ajax请求实现跨域(jsonP因为其实现机制原因故只能是GET请求) //url-----,字符串,用户要ajax请求的URL //callbackName,字符串,设置一个回调函数名。您只需要保证服务器端使用同名函数来包装json对象即可。一般服务器端可以类似于这样设置: response.write($Request['callback']+"({json对象})"),可保证与客户端设置一致。 //onsuccessfun,函数对象,表示请求成功后要执行的回调。(200状态码,且json状态为success) //onlogicError,函数对象,表示请求的逻辑失败后的回调。(也是200状态码,但json状态为fail)
function ajaxjsonp(url,callbackName,onsuccessfun,onlogicError) { //提前创建好回调函数 window[callbackName] = function (rel) { if (rel.success == true) { onsuccessfun(rel.data);//调用请求成功的处理函数 } else { onlogicError(rel.errormsg);//调用逻辑错误处理的函数 } };
//构造一个DOM向服务器发请求 var scriptdom = document.createElement("script"); var callbackRequest = "callback="+callbackName; url = url.indexOf("?")>0?url + "&" + callbackRequest:url+"?"+callbackRequest; scriptdom.src = url;//利用DOM向服务器发起GET请求 document.body.appendChild(scriptdom); } 使用实例: 当你页面需要使用jsonp跨域的时候,只需要这样调用即可: CYJLIB.ajaxjsonp("http://localhost:54675/","cyjddcallback",function (data) { document.getElementById("ttt").innerHTML = data.a },function (msg) { document.getElementById("ttt").innerHTML = msg;}); 以上语句中CYJLIB请忽略即可,我只是把ajaxjsonp函数放入了一个对象而已。 后面的传参中上文都有介绍,很容易理解。关于callbackName这个参数,只要你服务器像上文那样设置好了,那客户端就可以随意填写。 缺点: 我写的这个函数无法检测HTTP请求中的错误,也无法获取到请求过程中的状态---比如“正在请求”。 另外,jsonp对服务器来说是有安全危险的,比如任何人都可以用浏览器去调用你的接口,给你带来了流量损耗。 同时,浏览器这种机制(bug)也会让恶意的人利用,当他取得你页面相关权限后,来跨域注入恶意js代码到你的页面。 所幸,html5提供的XHR level2解决了这种安全问题。 另送上非跨域请求的ajax包装函数: //Ajax请求封装函数 //GorP,string类型,表示这个ajax请求使用Get还是Post方式 //欧尼 function ajax(GorP,url,onprocessfun,onhttpError,onlogicError) { //创建考虑兼容性的XMLHttpRequest对象 var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); //打开http连接准备向服务器指定的URL发送post请求(Get请求可能会有缓存问题,所以尽量用post请求) xmlhttp.open(GorP,true);
//定义好xmlhttp对象接收到返回状态值时的事件。 xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { clearTimeout(timer); //返回状态码4代表服务端已经完成了返回数据的任务。 //接下来判断http报文里的状态码 if (xmlhttp.status == 200) { var rel = JSON.parse(xmlhttp.responseText); if (rel.success = true) { onsuccessfun(rel.data);//调用请求成功的处理函数 } else { onlogicError(rel.errormsg);//调用逻辑错误处理的函数 } } } } //超时处理:放弃xhp请求,并调用onerror函数,把错误码给onerror。 timer = setTimeout(function () { if (xmlhttp) { xmlhttp.abort(); } onhttpError(xmlhttp.statusText); },20000); //上面定义好了xmlhttprequest对象,而且设置了该对象状态变化时的事件。接下来开始发送请求 xmlhttp.send(); onprocessfun(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |