前言:有时候一忙起来就没了时间观念,原来我已经有十多天没写博客了。一直想作跨域方面的尝试,无奈最近准备校招没时间动动手。今天就先讲讲JSONP吧,昨晚还在研究QQ空间日志里面网络图片的问题呢,我发现日志还提供了HTML模式,咱们能够利用img标签的src属性实现跨域请求,从本身的服务器里提取动态内容。php
JSONPjquery
在讲实现以前,咱们先来看看何为JSONP。如下是维基百科的解释:web
JSONP or "JSON with padding" is a communication technique used in JavaScript programs running in web browsers to request data from a server in a different domain, something prohibited by typical web browsers because of the same-origin policy. JSONP takes advantage of the fact that browsers do not enforce the same-origin policy on <script>
tags. Since it works through <script>
tags, JSONP supports only the GET request method. There are significant security implications and risks associated to using JSONP; unless you have no choice, CORS is usually the better choice.ajax
我粗陋翻译一下:JSONP又称JSON with padding,它是用在浏览器上运行的JS程序里的一项交互技术,目的是为了从不一样的服务器域名上请求数据。因为同源政策的限制,部分功能会受到浏览器的禁止。JSONP利用的是浏览器不会对<script>标签实施同源政策的状况。又由于它是经过<script>做用的,因此JSONP只支持GET请求方式。但值得注意的是,使用JSONP会存在安全隐患和危险。CORS(跨域资源共享,Cross-Origin Resource Sharing)是一个更为经常使用的佳选,除非你没得选。json
解释: 跨域
简单来讲就是,通常状况下,在本域名的页面想要获取其余域名下的数据是会受到限制的。可是在HTML页面中的<script>(img,iframe亦可)就突破了这种限制,能够经过src属性来访问其余域名并得到返回的数据,但这种方法并不安全,只能经过GET方法获取。浏览器
其实咱们日常稍加留意,就不难发现其实咱们日常在页面中使用CDN也是这个原理,咱们的页面一样能够访问其余服务器上的JS文件。缓存
如咱们经常使用的百度CDN,咱们一般在<head>里面加上是<script>标签就可使用其余服务器的CDN。安全
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script>服务器
只不过稍有不一样的是如今变为向服务器运行文件请求数据,而后再以JavaScript的形式返回。
客户端实现:
JSONP是一种非正式传输协议,具体传输内容以及格式能够由用户本身定义。不过我以为JSONP可能会在ES6中新增也说不定哦,到时候可能会规范传输格式。JSONP其中有一个要点就是容许用户传递一个callback参数给服务端,而后服务端输出的数据做为callback的参数再一并返回到客户端页面,最后根据参数在客户端页面执行这个回调函数,最终达到返回数据并处理的目的。
代码形式以下:
1 <head> 2 <meta charset="UTF-8"> 3 <title>JSONP</title> 4 <script type="text/javscript"> 5 var cbFn = function(str){ 6 alert(str); 7 } 8 </script> 9 <script src="http://www.sp0.baidu.com?data=value&cb=cbFn"></script> 10 </head>
首先要预约义一个回调函数,用于处理返回数据;其次请求数据的<script>标签的src要传递请求参数以及回调的函数名字到后台,这一点要沟通协调好。
因为在实际应用中请求地址、请求参数以及次数都是不固定的,因此咱们要把JSONP封装成一个函数,加强灵活性和复用性。
1 var s1; 2 function jsonp(url,data,cb){ 3 data.cb = cb?cb:"callback"; 4 data.t = new Date().getTime(); 5 for (var i in data){ 6 var str = i+"="+data[i]; 7 arr.push(str); 8 } 9 var str = url+"?"+arr.join("&"); 10 var headEl = document.getElementsByTagName("head")[0]; 11 if (s1){ 12 headEl.removeChild(s1); 13 } 14 s1 = document.createElement("script"); 15 s1.src = str; 16 headEl.appendChild(s1);
17 }
代码解释:首先给传递的数据中插入一个回调函数名和一个新的时间参数值,让后台获取你要回调的函数名以及防止调用缓存。接下来就是判断以前已是否发送过JSONP请求,若是存在,则删除重建。
服务端实现:
假设我在客户端执行了如下请求
1 jsonp("http://www.chengguanhui.com/test.php",{ 2 name:"ray", 3 age:23 4 },"cbFn"); 5 6 cbFn(str){ 7 alert(str); 8 }
那么HTTP传递的URL为http://www.chengguanhui.com/test.php?name=ray&age=23cb=cbFn&t=242566(某个不定时间值)
PHP代码:
1 <?php 2 require_once("common.php"); 3 $name = $_GET['name']; 4 $age = $_GET['age']; 5 $cb = $_GET['cb']; 6 $str = $name.$age; 7 echo $cb."(".$str.")"; 8 ?>
客户端接收到cbFn("ray23")并弹出对应内容。
JQ实现:
$.ajax(url,[settings])
1 $.ajax({ 2 type: "get", 3 url: "http://www.chengguanhui.com/test.php", 4 dataType: "jsonp", 5 data: "name=ray&age=23", 6 jsonp: "callback",//传递给请求处理程序或页面的,用以得到jsonp回调函数名的参数名(通常默认为:callback) 7 jsonpCallback:"handleFn",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也能够写"?",jQuery会自动为你处理数据 8 success: function(json){ 9 alert(json.name+json.age); 10 }, 11 error: function(){ 12 alert('fail'); 13 } 14 }); 15 });
$.getJSON(url,data,callback)
1 $.getJSON("http://www.chengguanhui.com/test.php",//若是请求值固定时,能够省略data参数而直接写在url参数里。 2 { 3 name:ray, 4 age:23 5 }, 6 function(data){ 7 $.each(data.items, function(i,item){ 8 alert(i+item); 9 }); 10 });
说明:原创文章,转载全文内容或非翻译内容时,请注明出处与做者。谢谢。