日期:2014-05-16  浏览次数:20410 次

dojo1.7翻译 ajax跨域请求(Getting Jiggy with JSONP)

原文地址: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访问而组成多个子域,以提供更强大的访问连接功能。