jsonp虽然以前实现过,但是只是依葫芦画瓢,并没有理解,今天在博客园里面找到http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html这篇文章,作者对其中jsonp进行了阐述,大概明白了其意思,其中有几句话我觉得比较有意思
2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>); 3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理; 2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
然后在wiki里面查查jsonp(http://en.wikipedia.org/wiki/JSONP),自己用代码在实现了一下,下面总结如下:
其中wiki中对jsonp的阐述有几点值得让人注意:
JSONP or "JSON with padding" is a communication technique used in JavaScript programs which run in Web browsers. It provides a method to request data from a server in a different domain, something prohibited by typical web browsers because of the same origin policy. Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. A few exceptions include the HTML <script> element. Exploiting the open policy for <script> elements, some pages use them to retrieve JavaScript code that operates on dynamically generated JSON-formatted data from other origins. This usage pattern is known as JSONP. Requests for JSONP retrieve not JSON, but arbitrary JavaScript code. They are evaluated by the JavaScript interpreter, not parsed by a JSON parser.
其中说到,web请求数据必须遵循same origin policy同源策略,否则将会被拒绝。但是有个例外是<script>元素却可以请求其它域。那它是怎么做的啦?
some pages use them to retrieve JavaScript code that operates on dynamically generated JSON-formatted data from other origins.
原来是从跨域服务器上 动态的生成了json格式的数据并返回为avascript代码。同时这样的策略是被jsonp所规定好的,jsonp请求返回的不是json,而是任意形式的js代码,这些代码是可以被javascript解释器所处理的。
wiki后面还给出了一个例子,说我们需要跨域去调用这样的一个url http://server2.example.com/Users/1234 返回的是
{ "Name": "Foo", "Id": 1234, "Rank": 7 }
在调用方server1中如下:
<script type="application/javascript"
src="http://server2.example.com/Users/1234">
</script>
The browser will, in order, download the script file, evaluate its contents, interpret the raw JSON data as a block, and throw a syntax error. Even if the data were interpreted as a JavaScript object literal, it could not be accessed by JavaScript running in the browser, since without a variable assignment object literals are inaccessible.
然后wiki解释,在server1中的web page,浏览器将会下载src中这个脚本,并且评估期内容,将返回的json数据当作快block处理,将会抛出语法错误。如果这个数据被js解释器翻译为一个js对象文本,它将不能被js访问,是因为它木有可访问的一个变量赋值对象的声明。
那我们应该如何正确的jsonp跨域啦?
wiki告诉我们我们P其实就是padding,我们应该用一个function(这个function已经定义了)去padding住json的data。比如这样的functionCall({"Name": "Foo", "Id": 1234, "Rank": 7});,就可以被js解释器处理了。
In the JSONP usage pattern, the URL request pointed to by the <script>'s src attribute returns JSON data, with a function call wrapped around it. In this way, a function that's already defined in the JavaScript environment can manipulate the JSON data. A JSONP payload might look like this: functionCall({"Name": "Foo", "Id": 1234, "Rank": 7}); The function call is the "P" of JSONP - the "padding" around the pure JSON, or according to some[1] the "prefix". By convention, the browser provides the name of the callback function as a named query parameter value, typically using the name jsonp or callback as the named query parameter field name, in its request to the server, e.g., <script type="application/javascript" src="http://server2.example.com/Users/1234?jsonp=parseResponse"> </script> In this example, the received payload would be: parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});
当然它后面又提到,需要用到一个url查询字段,jsonp和callback都可以跨域访问。callback是方面我们对json数据处理的。
现在我们再来看jsonp的实质:
下面我写了一个实例,服务端www.keily.com是wcf发布的restful服务,返回json格式的数据,前端www.rollng.com 用jsonp来跨域调用。
www.keily.com
[WebGet(UriTemplate = "persondetail")] public IList<PersonEntity> GetPerson() { return _personBLL.GetPerson(); }
www.rollng.com
<script type="text/javascript"> var jsonpHandler = function(data){ debugger; console.log(data); }; </script> <script src="http://www.keily.com/restfulservices/person/persondetail?callback=jsonpHandler" type="text/javascript"></script>
来看看运行调用结果
返回的是callback这个field对应的value:jsonpHandler包起来的json数据,js解释器就会把这段数据当作block处理,解释这段语法,找到回调函数jsonpHandler处理其中的json数据。
同时我们也注意到,jsonp的确是请求的Scripts,而不是ajax的XHR。
ok。