原文地址:http://dojotoolkit.org/documentation/tutorials/1.7/jsonp/
难度:初级
版本:1.7
JSONP已经成为了一种跨用请求的通过技术了。在这个教程中,你可以学到如何使用JSONP来进行跨域请求。
开始教程
dojo的基础ajax模块已经提供了简单有效的动态ajax功能,但是,并不能使用dojo的xhr进行安全的跨域请求,怎么办?大多数的浏览器都实现了W3C组织的Cross-Origin Resource Sharing的规范来支持跨域请求的功能,但不是所有的浏览器都支持的。有方法解决,我们可以使用JSONP技术来支持跨域的请求。
Bob Ippolito在2005年就发表过文章来介绍JSOPN技术,现在已经包括有Google,Twitter,Facebook等都提供了这种服务的全部API,DOJO的dojo/io/script模块就无缝的支持了读取这种服务的功能,而且使用起来非常的简单。
那到底什么是JSONP技术呢?不像XHR只能在一个域里来请求.JSONP通过动态的加载<script>标签来发起请求,并在有返回值时执行回调函数。如一个请求为endpoint?q=dojo&callback=callme 那么他的返回值可能是callme({id: "dojo", some: "parameter"})
当浏览器执行到这个脚本时,它就会调用callme()这个方法,并把相应的参数传递过去。当本地的程序有定义callme这个方法时,将会接收这个方法。注意,这个函数是从第三方服务器中传过来的并执行的,所以你要确认这个第三个的合法和安全性。这不是让你禁用JSONP,而是让你只和信任的服务进行请求。
使用JSONP进行跨域请求可以降低浏览器与服务器的连接量。浏览器限制在同一时间对服务器发出的请求量。最坏的情况,在IE6上同时会有两个连接,但在最新的浏览器时会同时有6到8个连接。但使用跨域请求资源时,它将不再计算你同时连到服务器中的连接数
dojo/io/script 将会自动创建脚本元素和执行回调函数,并且也是使用dojo是常用的迟延技术
//include the script modules require(["dojo/io/script", "dojo/dom", "dojo/_base/array", "dojo/domReady!"], function(ioScript, dom, arrayUtil){ //wait for the page and modules to be ready... //Make a request to search twitter for #dojo ioScript.get({ url: "http://search.twitter.com/search.json", content: {q: "#dojo"}, callbackParamName: "callback" }); });
代码中基本和dojo/_base/xhr中的一样,只是加入了callbackParamName的属性,这个属性是dojo以参数的形式告诉服务器,要执行哪个回调函数。这有点像是通过服务改变服务,从这点来说,你可以把它当成是有别的附加的功能函数。下面来看一个有更多内容的例子
//first do the io script request ioScript.get({ url: "http://search.twitter.com/search.json", content: {q: "#dojo"}, callbackParamName: "callback" }).then(function(data){ //Loop through the data results and create an array containing //each tweet's text wrapped in an LI var tweets=[]; arrayUtil.forEach(data.results, function(item,idx){ tweets.push("<li>" + item.text + "</li>"); }); //join the array of LIs together and make them the //innerHTML of the content holding node. dom.byId("tweets").innerHTML = tweets.join(""); });
代码很漂亮,我们再来加一点动画的效果
require(["dojo/io/script","dojo/domConstruct", "dojo/domReady!"], function(ioScript, domConstruct){ //make the request just as before ioScript.get({ url: "http://search.twitter.com/search.json", callbackParamName: "callback", content: {q: "#dojo"} }).then(function(data){ //we're only interested in data.results, so strip it off and return it return data.results; }).then(function(results){ //create an interval timer that will remove the first item in //the array and render it. Stop the loop when the results have been //exhausted. var handle = setInterval(function(){ domConstruct.create("li", {innerHTML: results.shift().text},"tweets"); if (results.length < 1){ clearInterval(handle); } }, 200); }); });
通过JSONP来动态生成脚本的有一个缺点,它不能返回错误信息。如果浏览器的请求遇到了404或500错误,那么dojo/io/script的回调函数将没有任何反应。为了防止你的空等待,你可以设置一个请求时间timeout。如果请求没有及时返回信息则被timeout打断。
结论
JSONP可以让你能通过访问不同的服务器而获得大量丰富的资源。大多数服务提供商都提供了大量的JSONP服务。及时是在同一个项目中,你也可以通过使用JSONP访问而组成多个子域,以提供更强大的访问连接功能。