天天看点

XMLHttpRequest VS. JSONP

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

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

{
"completed_in":0.044,
"max_id":306750251744784385,
"max_id_str":"306750251744784385",
"page":1,
"query":"hfhtml5",
"refresh_url":"?since_id=306750251744784385&q=hfhtml5",
"results":[],
"results_per_page":15,
"since_id":0,
"since_id_str":"0"
}
           

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

<!doctype html>
<html >
<head>
	<title>Using Canvas</title>
	<meta charset="utf-8" />
	<script>
		
		function createList(attribute) {
			var element = document.createElement("li");
			element.innerHTML = attribute;
			var list = document.getElementById("list");
			list.appendChild(element);
		}
		var request = new XMLHttpRequest();
		request.open("GET", "data.json");
		request.onload = function() {
			if(request.status == 200) {
				
				var text = request.responseText;
				var object = JSON.parse(text);
				createList("completed_in:" + object.completed_in);
				createList("max_id:" + object.max_id);
				createList("max_id_str:" + object.max_id_str);
				createList("page:" + object.page);
				createList("refresh_url:" + object.refresh_url);
				createList("results:" + object.results);				
			}
		};
		request.send(null);
	</script>
</head>
<body>	
	<ul id="list">
	
	</ul>
</body>
</html>
           
XMLHttpRequest VS. JSONP

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

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

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

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

XMLHttpRequest VS. JSONP

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

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

request.open("GET", "http://search.twitter.com/search.json?q=hfhtml5");
           

重新加载该页面:

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

XMLHttpRequest VS. JSONP

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

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

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

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

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

alert("woof");      

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

<!doctype html>
<html >
<head>
	<title>Using Canvas</title>
	<meta charset="utf-8" />

</head>
<body>	
	<script src="http://wickedlysmart.com/hfhtml5/chapter6/dog.js"></script>
</body>
</html>
           

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

访问该页面后:

XMLHttpRequest VS. JSONP

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

再继续:

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

animalSays("dog", "woof");      

怎么让该方法被调用呢?我们可以在本地页面创建该函数:

<!doctype html>
<html >
<head>
	<title>Using Canvas</title>
	<meta charset="utf-8" />
	<script>
		function animalSays(name,bark) {
			alert(name + ":" + bark);
		}
	</script>
</head>
<body>	
	<script src="http://wickedlysmart.com/hfhtml5/chapter6/dog2.js"></script>
</body>
</html>
           

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

试着刷新下页面:

XMLHttpRequest VS. JSONP

看到效果了吧!

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

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

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

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

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

<!doctype html>
<html >
<head>
	<title>Using Canvas</title>
	<meta charset="utf-8" />
	<script>
		function animalSays(animal) {
			var type = animal.type;
			var sound = animal.sound;
			alert("type:" + type + ",sound:" + sound);
		}
	</script>
</head>
<body>	
	<script src="http://wickedlysmart.com/hfhtml5/chapter6/dog3.js"></script>
</body>
</html>
           

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

刷新下页面:

XMLHttpRequest VS. JSONP

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

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

我们可以通过URL来指定:

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

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

XMLHttpRequest VS. JSONP

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

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

继续阅读