JSONP的原理
JSONP 是一种【请求一段 JS 脚本,把执行这段脚本的结果当做数据】的玩法。
所以,你能 POST 一段通过 script 标签引入的脚本吗?
(如果看过 JSONP 库的源码就知道,常见的实现代码其实就是 document.createElement(‘script’) 生成一个 script 标签,然后插 body 里而已。在这里根本没有设置请求格式的余地)。
所以JSONP的实现原理就是创建一个script标签, 再把需要请求的api地址放到src里. 这个请求只能用GET方法, 不可能是POST
JSONP的例子一
域名A中的JS代码AJAX请求域名为B的服务器数据,这就是跨域AJAX请求,默认情况下是不行的。
但是HTML中有地方可以跨域请求,比如img script标签,它们的src属性指向的地址可以是不在域名A下的(即跨域)。
那有人就利用了上面的特点,选择了script中src能够跨域获得内容的特性,研究出了JSONP这种hack协议。(src中请求都是GET)
那假设JSONP请求如下:
jsonp({
url: 'http://path/to/server/b',
params: {A: a, B: b},
success: function myCallback (response) {}
})
背后其实在进行:
1.拼接一个script标签,,从而触发对指定地址的GET请求
2.那服务器端对这个GET请求进行处理,并返回字符串 “myCallback(‘response value’)”
3.那前端script加载完之后,其实就是在script中执行myCallback(‘response value’)
4.是不是就完成了跨域的请求,
5.是不是就是只能用GET
所以jsonp不会对服务器端代码或者内容做更改,因为它只能发送get请求
转自:https://segmentfault.com/q/1010000009708151
JSONP的例子二
一、JSONP
由于同源策略不会阻止动态脚本的插入到文档中去,所以催生出了一种很常用的跨域方式: JSONP(JSON with Padding)。
原理说起来也很简单:
假设,我们源页面是在a.com,想要获取b.com的数据,我们可以动态插入来源于b.com 的脚本:
script=document.createElement("script");
script.type="text/javascript";
script.src="http://www.b.com/getdata?callback=demo";
function demo(data) {
console.log(data.msg);
}
这里,我们利用动态脚本的src属性,变相地发送了一个http://www.b.com/getdata?callback=demo的GET请求。这时候,b.com页面接受到这个请求时,如果没有JSONP,会正常返回json的数据结果,像这样:
{msg:"helloworld"}
而利用JSONP,服务端会接受这个callback参数,然后用这个参数值包装要返回的数据:
demo({msg:"helloworld"});
这时候,如果a.com的页面上正好有一个demo 的函数:
function demo(data) {
console.log(data.msg);
}
当远程数据一返回的时候,随着动态脚本的执行,这个demo函数就会被执行。
到这里,你应该能明白这个技术为什么叫JSONP了吧?就是因为使用这种技术服务器会接受回调函数名作为请求参数,并将JSON数据填充进回调函数中去。
JSONP的优缺点
虽然JSONP在跨域ajax请求方面有很强的能力,但是它也有一些缺陷。
首先,它没有关于JSONP调用的错误处理,一旦回调函数调用失败,浏览器会以静默失败的方式处理。
其次,它只支持GET请求,这是由于该技术本身的特性所决定的。因此,对于一些需要对安全性有要求的跨域请求,JSONP的使用需要谨慎一点了。
由于JSONP对于老浏览器兼容性方面比较良好,因此,对于那些对IE8以下仍然需要支持的网站来说,仍然被广泛应用。不过,针对高级浏览器,建议还是使用接下来会介绍的CORS 方法。
JSONP是同步还是异步
首先搞清楚,在软件开发领域,在前端领域,同步和异步的概念分别是什么。
我在wikipedia上找到一个解释。其实可以简单的理解为:能立刻得到结果的,不影响代码顺序执行的,都是同步的。反之,都是异步的。
alert, confirm, prompt都需要较长时间执行,但它们并不影响代码顺序执行,所以,它们是同步的。
setTimeout, setInterval, ajax等网络请求方式,这些都是需要回调函数的,不能立刻得到结果,而且也不阻塞代码顺序执行,所以这些都是异步的。
再来看什么是jsonp:
jsonp可以理解为从网络加载的一段脚本,不是表达式,而是语句。通常的表现形式为,在请求的URL中传入一个要执行的函数的方法名,而在应答中调用这个方法。
所以,jsonp是异步的,并且是可以跨域请求的异步。
JSONP异步的理解
ajax其实用它主要就是因为它的异步,它去服务器端取数据,html页面可以在它取数据期间接着走下面的,等ajax取回数据了再处理;
jsonp也是利用回调函数,去指定服务器上取数据的时候不用等待,等它取回来了直接用回调函数一处理,也达到了异步的效果呀
JSONP异步的例子
你可以试试写个内容如下的a.js
alert('a')
然后
var scn = document.createElement('script');
scn.src = 'a.js';
document.getElementsByTagName('head')[0].appendChild(scn);
alert('b');
看看执行顺序是先a后b
还是先b后a
就知道是同步异步
你还可以在以上代码中加入async 来看看是否造成差异
执行结果是先b后a