JSONP是JSON with padding(填充式JSON或参数式JSON)的简写。JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。
一般通过Ajax进行通信时,都会受到浏览器同源策略的约束,难以访问跨域资源。这里的跨域指的是:协议 域名 端口号 只要其中的一个不同,都属于跨域。于是,我们发现例如<img><script><iframe>这些元素只要可以使用src属性,便可以轻易的访问跨域资源。当然,前提是你必须确保你访问的资源是安全的,没有恶意代码注入,不会对你的浏览器造成伤害。而通过JSONP进行跨域通信,实际上就是加载外部的.js文件。用到了<script src=............ >。来看一段代码吧!
function handleResponse(response){ alert("You're at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name); } var script = document.createElement("script"); script.src = "http://freegeoip.net/json/?callback=handleResponse";//一般JSONP请求的网址后面都带有json字样,说明回调函数的数据格式是json。出于性能优化方面的考虑,需将回调函数的名字传递给后台的服务器。这样后台可以直接拿来用。 document.body.insertBefore(script, document.body.firstChild);
这段代码是请求地理定位。 我对JSONP后台的工作原理的理解是:当前端发出请求后,跨域的服务器会将以callback参数为函数名,包裹住数据(当然这些数据都是JSON格式),当响应返回时,接着执行函数,这样,用户便可以根据自己的需要制定函数来处理返回的数据了。至于为什么需要JSON 格式的数据呢?我认为:恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
但是我们在日常中,所需要访问的跨域资源一般有很多个js文件,而JSONP服务的对象也有很多个。那如何找到我们需要的信息呢?这时,我们可以给url传递一个字符串来动态生成js脚本。例如:
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
这行代码中传入了code参数来动态生成有关于航班CA1998的信息。那么服务器端传回来的数据是:
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
接着执行上面的函数得到用户想要的结果。
从上面的代码可以看出来在这里我们是动态地生成JSON数据格式的js文件的,而不是将其写死。这其中的奥秘便是code参数了,同样,这使得客户端与服务器之间的交互更便捷了。用户可以直接告诉服务器我需要什么,然后你给我提出相应的信息。
JSONP的优点在于它可以直接访问响应文本,支持在浏览器与服务器之间的双向通信。不过,JSONP也有不足:
1.JSONP是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码,而此时除了完全放弃JSONP调用之外,没有办法追究。
2.要确定JSONP请求是否失败并不容易。虽然HTML5给<script>元素新增了一个onerror事件处理程序,但目前还没得到任何浏览器的支持。为此,开发人员不得不使用计时器检测指定时间内是否收到了响应。但就算这样也不能尽如人意,毕竟不是每个用户上网的速度和带宽都一样。