网上讲解jsonp的文章很多,但究竟何为jsonp?
有些人会说,ajax可以通过jsonp的方式来进行跨域访问数据
这个说法是完全错误的,首先ajax不允许跨域,再者,通过jsonp跨域并不是ajax的功能,只是这种请求数据的方式与ajax雷同而已。
废话不多说,下面进入今天的正题:何为jsonp,以及他的工作原理。
ajax只能访问同域名下的文件
大家都知道通过ajax可以访问同一个域名下的其他文件,例如通过ajax可以在webqq.html(网址:http://192.168.7.167/js_test/webqq.html)访问a.html(网址:http://192.168.7.167/a.html),虽然这两个文件没有在同一级目录,但是由于他们都位于“http://192.168.7.167”这个域名下,所以可以访问到a.html。
不过很多时候我们需要从一个域名下的文件访问另一个域名下的文件,例如:webqq.html(网址:http://192.168.7.167/js_test/webqq.html)访问b.html(网址:http://zhinengshe.com/b.html),这时就涉及到了跨域,ajax此时已经歇菜了,如下图
通过script标签挽救跨域
此时我们来看另一个例子:
我们在webqq.html(网址:http://192.168.7.167/js_test/webqq.html)下编写如下代码:
<script type="text/javascript" src="http://zhili.com/b.js"></script><!--b.js文件内容是function show(){return '我是远程数据'}--> <script type="text/javascript"> alert(show()); </script>这时我们奇迹般的发现,页面弹出了'我是远程数据',不过你有没有注意到我们已经实现跨域访问数据了?小伙伴们,有没有jsonp如此简单的赶脚,事实就是如此。
*小伙伴们注意了,现在我们扯到ajax了
不过为了加强大家理解,我再来简单扯一下简单扯一下ajax的工作原理,此处以get请求为例,我们客户端请求的地址都是类似这种形式的“http://192.168.7.167/api.PHP?a=lgn&user=charts&pass=charts&cb=success2”,至于’?‘后的数据我们统称为参数,后台能拿到这里面所有的参数,而后台就是根据这些“参数”来确定返回给我们的数据
现在我们回到jsonp的话题来,既然这样我们直接在webqq.html(js_test/webqq.html)这样写不就皆大欢喜了?
<script type="text/javascript"> function success2(data){ console.log(data); }; </script> <script type="text/javascript" src="http://zhili.com/b.js?a=lgn&user=charts&pass=charts&cb=success2"></script>
接口规定:b.js会回调名为cb属性值的函数,由此可知,我们只需要在前台定义回调函数“success2”就好,至于什么时候调用,这不关我们的事,此时我们实现了跨域也拿到了数据data。由于script标签只会被页面读一次,所以异步更改script标签的src已不能满足我们的要求,但我们有另一个办法,也就是动态创建script标签,这样就可以达到,每次更改地址浏览器都会读了,例子如下:
function fnOrder(data) { var data = json2str(data); var order = document.getElementById('orderOnce'); if ( !! order) { document.getElementsByTagName('body')[0].removeChild(order); }; var oSc = document.createElement('script'); oSc.id = 'orderOnce'; oSc.src = 'http://zhinengshe.com/exercise/im/api.PHP?' + data; document.getElementsByTagName('body')[0].appendChild(oSc); };//动态创建script标签 function json2str(json) { var arr = []; for (var i in json) { arr.push(i + '=' + json[i]); var str = arr.join('&'); }; return str; };//将json转化为url后跟的参数形式 function success2(data) { console.log(data); };//后台回调函数 fnOrder({ a: 'lgn',user: encodeURIComponent(oUser.value),pass: oPass.value,cb: 'success2' });
到这里,jsonp该告一段落了,是不是发现很简单啊,总结一点,jsonp只是通过script标签可以跨域的特性来获得数据的一种行为,和ajax事实上半毛钱关系都木有
后记:
至于有些人说用jquery中的ajax方法可以把dataType设置成jsonp就可以跨域了,拜托你们可以看看jquery源代码对$.ajax的封装,看完你就会发现也是相同的原理,虽然形同jquery中ajax请求,但是$.ajax方法内部对于其dataType参数做判断后做了相应处理,那时早已不是通过xmlHTTPRequest对象来实现数据的访问了