XMLHttpRequest VS. JSONP

来源:互联网 发布:软件著作权代理费 编辑:程序博客网 时间:2024/05/24 07:38

    当我们利用XMLHttpRequest对象从本地服务器获取数据时是可以的。

    假设我们使用的数据格式为JSON(JavaScript Object Notation),并且我们在本地服务器上部署了一个样本数据data.json:

[plain] view plain copy
  1. {  
  2. "completed_in":0.044,  
  3. "max_id":306750251744784385,  
  4. "max_id_str":"306750251744784385",  
  5. "page":1,  
  6. "query":"hfhtml5",  
  7. "refresh_url":"?since_id=306750251744784385&q=hfhtml5",  
  8. "results":[],  
  9. "results_per_page":15,  
  10. "since_id":0,  
  11. "since_id_str":"0"  
  12. }  

好了,有了数据,我们试着编写一个简单的页面文件来获取该数据:(该页面文件和data.json位于同一目录下)

[html] view plain copy
  1. <!doctype html>  
  2. <html lang="en">  
  3. <head>  
  4.     <title>Using Canvas</title>  
  5.     <meta charset="utf-8" />  
  6.     <script>  
  7.           
  8.         function createList(attribute) {  
  9.             var element = document.createElement("li");  
  10.             element.innerHTML = attribute;  
  11.             var list = document.getElementById("list");  
  12.             list.appendChild(element);  
  13.         }  
  14.         var request = new XMLHttpRequest();  
  15.         request.open("GET", "data.json");  
  16.         request.onload = function() {  
  17.             if(request.status == 200) {  
  18.                   
  19.                 var text = request.responseText;  
  20.                 var object = JSON.parse(text);  
  21.                 createList("completed_in:" + object.completed_in);  
  22.                 createList("max_id:" + object.max_id);  
  23.                 createList("max_id_str:" + object.max_id_str);  
  24.                 createList("page:" + object.page);  
  25.                 createList("refresh_url:" + object.refresh_url);  
  26.                 createList("results:" + object.results);                  
  27.             }  
  28.         };  
  29.         request.send(null);  
  30.     </script>  
  31. </head>  
  32. <body>      
  33.     <ul id="list">  
  34.       
  35.     </ul>  
  36. </body>  
  37. </html>  


页面确实返回了我们从本地服务器获取的数据,我们对其进行了解析。(我们从XMLHttpRequest对象的属性responseText是json字符串,如果需要将其封装成对象,可以使用JSON.parse方法,如果想将对象字符串化,可以使用parse的对称方法JSON.stringnify。)


现在Web Services很流行,它们可以为我们提供需要的数据,比如实时天气信息,比如公交信息,比如其它用户感兴趣的内容。

好了,Twitter为我们提供了一个数据源URL: http://search.twitter.com/search.json?q=hfhtml5  (有些地方需要翻墙。需要的密我)

其实它的内容和data.json文件一样:


现在我们来修改一下页面文件,我们使用外部服务器(相对本地服务器而言)来获取数据:

其实只需要修改open方法的第二个参数url:

[javascript] view plain copy
  1. request.open("GET""http://search.twitter.com/search.json?q=hfhtml5");  

重新加载该页面:

咦?页面怎么是空白的。到底怎么回事呢?如果你用的是Google Chrome浏览器的话,可以借助自带的JavaScript控制台(Ctrl+Shift+J)查看哪里出错了。



原因找到了,因为XMLHttpRequest对象不允许跨服务器发送请求,因此该请求被拒绝,外部服务器根本就不知道有请求发送给它。这属于一个跨域安全问题(Cross-Domain Security Issues)。


那么该怎么办呢?既然XMLHttpRequest因为考虑到安全性不允许发送请求到外部服务器,只好寻找其它的办法。

想必大家看过文章标题的都应该猜出,我们可以使用JSONP ( JSON with Padding)。

在讲JSONP之前,先看看几个和JS有关的简单例子:

http://wickedlysmart.com/hfhtml5/chapter6/dog.js 这个URL(无需翻墙)返回的是一个JS文件,它的内容很简单,就是

alert("woof");
我们编写一个简单的本地服务器页面来加载该JS文件。

[html] view plain copy
  1. <!doctype html>  
  2. <html lang="en">  
  3. <head>  
  4.     <title>Using Canvas</title>  
  5.     <meta charset="utf-8" />  
  6.   
  7. </head>  
  8. <body>      
  9.     <script src="http://wickedlysmart.com/hfhtml5/chapter6/dog.js"></script>  
  10. </body>  
  11. </html>  

在body标签内部添加了一个script标签,该标签的src属性指向了外部服务器的js文件。

访问该页面后:


这说明了什么?说明了通过加载外部服务器的js文件,可以调用本地浏览器的内置对象的方法(比如window.alert方法)


再继续:

http://wickedlysmart.com/hfhtml5/chapter6/dog2.js 该js文件的内容是:

animalSays("dog", "woof");
怎么让该方法被调用呢?我们可以在本地页面创建该函数:

[html] view plain copy
  1. <!doctype html>  
  2. <html lang="en">  
  3. <head>  
  4.     <title>Using Canvas</title>  
  5.     <meta charset="utf-8" />  
  6.     <script>  
  7.         function animalSays(name,bark) {  
  8.             alert(name + ":" + bark);  
  9.         }  
  10.     </script>  
  11. </head>  
  12. <body>      
  13.     <script src="http://wickedlysmart.com/hfhtml5/chapter6/dog2.js"></script>  
  14. </body>  
  15. </html>  

我们增加了一个自定义函数animalSays,该函数接受两个参数,一个是动物名字,一个是动物叫声,另外我们把script标签的属性也修改成另外一个文件。

试着刷新下页面:


看到效果了吧!


好了,有了以上的基础,我们就可以实现从外部服务器获取我们需要的数据了。

只要在外部服务器中生成json数据格式,然后传递给指定的函数即可。

比如:http://wickedlysmart.com/hfhtml5/chapter6/dog3.js 它的内容是

var animal = { "type": "dog", "sound": "woof" };animalSays(animal);

我们想要得到该外部服务器上的数据,于是编写了该页面文件:

[html] view plain copy
  1. <!doctype html>  
  2. <html lang="en">  
  3. <head>  
  4.     <title>Using Canvas</title>  
  5.     <meta charset="utf-8" />  
  6.     <script>  
  7.         function animalSays(animal) {  
  8.             var type = animal.type;  
  9.             var sound = animal.sound;  
  10.             alert("type:" + type + ",sound:" + sound);  
  11.         }  
  12.     </script>  
  13. </head>  
  14. <body>      
  15.     <script src="http://wickedlysmart.com/hfhtml5/chapter6/dog3.js"></script>  
  16. </body>  
  17. </html>  

这里传递的是animal对象,该对象包含type和sound属性。(记得修改script标签的属性值)

刷新下页面:


哈哈,看到了吧,外部服务器端的数据就这样轻松的获取到了。


有个问题,外部服务器怎么知道我们本地服务器页面的函数名呢?

我们可以通过URL来指定:

http://search.twitter.com/search.json?q=hfhtml5&callback=myCallback

我们可以指定callback的值来告诉外部服务器本地页面的函数名字。


看到没有,该js的函数名就是URL尾部指定的名字


需要注意的是,使用JSONP存在安全问题,除非我们信任这些网站,比如Twitter,Facebook,google,否则请不要轻易加载它们的数据文件。而XMLHttpRequest则比JSONP更加安全,但是访问外部服务器受限。

0 0
原创粉丝点击