这是jquery api文档对跨域请求的解析:如果获取的数据文件存放在远程服务器上(域名不同,也就是跨域获取数据),则需要使用JSONP类型。使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面。服务器端应当在JSON数据前加上回调函数名,以便完成一个有效的JSONP请求。如果要指定回调函数的参数名来取代默认的callback,可以通过设置$.ajax()的jsonp参数。
我们通过demo来参悟上面的解析:
$.ajax({ type: "get", url: "http://www.yourdomain.com/site/test",//实际上访问时产生的地址为: http://www.yourdomain.com/site/test?callback=jsonpCallback&id=1 data: { id: 1 }, dataType: "jsonp", success: function (data) { alert(data.statu); }, error: function (XMLHttpRequest,textStatus,errorThrown) { alert(XMLHttpRequest.status); alert(XMLHttpRequest.readyState); alert(textStatus); } });
上面就是一个最简单的跨域访问请求了。好了,来说说跟普通ajax的区别。首先实际上访问时的地址为:
http://www.yourdomain.com/site/test?callback=随机数&id=10。参照api定义:
使用这种类型的话,会创建一个查询字符串参数 callback=? ,这个参数会加在请求的URL后面。
这个随机数是jQuery自动生成的。采用jsonp类型情况下,最终生成的url就是如此的。
接下来,看看后台:
服务器端应当在JSON数据前加上回调函数名,以便完成一个有效的JSONP请求。
这是服务器(C# MVC)的代码:
[HttpGet] public string test(string callback, string id) { return callback + "(" + "{\"statu\":" + id + "});"; }
一个有效的JSONP请求,需要在JSON数据前加上回调函数名。回调函数名是上面url中callback传递过来的值。此时服务器传递过来的值为:
jQuery18308788135794457048_1419557549884({"statu":"1"});
alert(data.statu);也能正确的输出“1”。有人会说json数据前还有回调函数名么,不用处理也能正常输出data.statu??是的,这就是JSONP。
至此,API的前3句已经解析清楚了。就剩后半句了。上面的callback是jQuery随机生成的,回调函数名也是固定为callback,倘若用户要自己定义呢?这就需要用到最后一句话了。
如果要指定回调函数的参数名来取代默认的callback,可以通过设置$.ajax()的jsonp参数。
ajax代码如下:
$.ajax({ type: "get", url: "http://www.yourdomain.com/site/test",//实际上访问时产生的地址为: http://www.yourdomain.com/site/test?mycallback=jsonpCallback&id=1 data: { id: 1 }, dataType: "jsonp", jsonp: "mycallback", jsonCallback: "jsonpCallback", success: function (data) { alert(data.statu); }, error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
} });
看到代码应该懂了吧。jsonp属性是设置传递过去的请求参数名的。jsonCallback属性则是自定义传递过去的参数。此时实际访问的url为:
http://www.yourdomain.com/site/test?mycallback=jsonpCallback&id=1
接下来就不细说了。后台接收代码:
[HttpGet] public string test(string mycallback, string id) { return mycallback + "(" + "{\"statu\":" + id + "});"; }
接收过来的数据:
jsonpCallback({"statu":"1"});
强调一下的就是。JSONP类型 ajax只支持get请求,post请求的情况已经测试过,是不行的。
至此,api的解析全部解析透了。
接下来,就是曲折版了。
function test() { alert("I am back~~"); } $.ajax({ type: "get", //async: false, url: "http://www.yourdomain.com/site/test", //实际上访问时产生的地址为: test?callback=jsonpCallback&id=10 data: { id: 10 }, cache: false, //默认值true dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback) jsonpCallback:"test", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名 //如果这里自定了jsonp的回调函数,则回调函数先起作用,后是success函数 success: function (data) { alert(data.statu); //alert(json.message); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(XMLHttpRequest.status); alert(XMLHttpRequest.readyState); alert(textStatus); } });
假如你传递过去的jsonpCallback参数为一js函数的话,也是可以的。成功回调之后,会首先调用jsonpCallback函数,然后是success函数。也就是会先alert("I am back~"),后alert(10)。
注意:jsonpCallback属性不能为匿名函数。即不能如下:
$.ajax({ type: "get", //async: false, url: "http://www.yourdomain.com/site/test4", //实际上访问时产生的地址为: test4?callback=undefinedk&id=10 data: { id: 10 }, cache: false, //默认值true dataType: "jsonp", jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(默认为:callback) jsonpCallback: function () { }, //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名 //如果这里自定了jsonp的回调函数,则回调函数先起作用,后是success函数 success: function (data) { alert(data.statu); //alert(json.message); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(XMLHttpRequest.status); alert(XMLHttpRequest.readyState); alert(textStatus); } });
这样的话,能正常返回。但是会先跑匿名函数,然后跑error函数。