[url=http://images.cnblogs.com/cnblogs_com/rush/201205/2012051521235522.png][img]http://files.jb51.net/file_images/article/201208/2012080212001017.png[/img]
[/url]
图6跨源请求过程
大家注意到同源请求中我们使用的是JSON格式,但在跨源请求中却是使用JSONP,这时大家可能有点困惑,坦然我刚开始学习的时候也是这样的。
首先我们必须理解JSON和JSONP的区别:JSON是一种数据格式,而JSONP像是通过一个方法名来封装JSON格式;由于浏览器允许跨源请求<script>资源,如我们的HTML页面代码中使用了Google的jQuery库,当我们Web程序发送跨源请求后,服务器给我们提供响应数据,但服务器无法预知接受JSON数据的方法名,所以我们要提供一个方法名。
Ajax跨源请求
跨域请求数据解决方案主要有如下解决方法:
JSONP方式
表单POST方式
服务器代理
Html5的XDomainRequest
Flash request
在介绍JSONP方式解决跨域请求数据之前,首先我们看看JSONP的定义。
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过Javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
由于同源策略的限制,XMLHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。
假设博客园提供一个API接口:http://www.cnblogs.com/hotblogs/json?,供开发者调用获取热门博文。
这里我们可以通过两种方式调用该接口:
1. 用Javascript定义回调函数
其实,通过Javascript定义回调函数调用该接口比较直观,我们只需告诉服务器接收数据的方法名就OK了,比如:
http://www.cnblogs.com/hotblogs/json? callback=myFunction
其中myFunction是我们在页面自定义的函数用来接收服务器回传的数据,myFunction的定义如下:
[url=http://weibo.com/DOMAIN]':WEIBO_TEXT<div class="time">AGO</div>';
// Appends weibos into html page.
for (var i = 0; i < data.length; i++) {
$(JQWeibo.appendTo).append(
html.replace('WEIBO_TEXT', JQWeibo.ify.clean(data[i].text))
// Uses regex and declare DOMAIN as global, if found replace all.
.replace(/DOMAIN/g, data[i].user.domain)
.replace(/USER/g, data[i].user.screen_name)
.replace('AGO', JQWeibo.timeAgo(data[i].created_at))
);
}
}
})
}
现在,我们使用$.ajax()方法向微博API发送跨源请求,而且我们向API传递了JQWeibo.appKey和JQWeibo.numWeibo,当请求完成后,调用Success()方法把JSON数据插入的页面当中。
页面的HTML代码如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Weibo Feed</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/WeiboFeed.css">
</head>
<body>
<div id="jsWeibo"></div>
</body>
</html>
[img]http://files.jb51.net/file_images/article/201208/2012080212001019.png[/img]
图8 跨源数据
如上图所示,我们使用$.ajax()方法调用公共微博接口,当成功获取服务器回调数据插入到我们的页面当中。
1.1.3 总结
本文主要介绍了Ajax在同源请求适用性,但在跨源请求中其存在的局限性,进而介绍Ajax和JSONP在跨源请求下解决方法。
回答qianlifeng关于跨源请求的几个问题:
1.一般的跨源不用jsonp请求为什么会报错?和同源的不都是一个请求么?(可能对ajax了解不深)
答:首先跨源请求的解决方法不仅仅有JSON,本文中提及了其他方法,如:表单POST方式、服务器代理、Html5的XDomainRequest和Flash request等;而你提到报错,我觉得你首先要确认数据格式是否正确。关于跨原请求和同源请求本文已经给出了介绍。
2.关于“用Javascript定义回调函数”那块看的不是很明白。传递当前页面的一个js方法给跨源服务器,为什么就能跨源请求了呢?(JSONP?) 服务端根据这个js方法做了什么操作啊?
答:首先我们理解JSON是一种数据格式,而JSONP像似通过一个方法名来封装JSON格式;而跨源请求不是说指定一个回调函数实现的,而是我们利用了浏览器允许跨源请求<script>资源,你也可以我的HTML代码中使用的是Google提供的jQuery库,这也说明了<script>资源可以跨源请求。当我们发送跨源请求后,服务器会返回JSONP,但服务器无法预知接受JSON数据的方法名,所有我们要把函数名告诉(传递)服务器。
[url=https://developer.mozilla.org/en/XMLHttpRequest]https://developer.mozilla.org/en/XMLHttpRequest[/url]
[url=http://www.w3schools.com/xml/xml_http.asp]http://www.w3schools.com/xml/xml_http.asp[/url]
[url=http://msdn.microsoft.com/en-us/library/windows/apps/cc836466%28v=vs.85%29.aspx]http://msdn.microsoft.com/en-us/library/windows/apps/cc836466%28v=vs.85%29.aspx[/url]
[url=http://ntesmailfetc.blog.163.com/blog/static/206287061201241011546581/]http://ntesmailfetc.blog.163.com/blog/static/206287061201241011546581/[/url]
[url=http://justcoding.iteye.com/blog/1366102]http://justcoding.iteye.com/blog/1366102[/url]
[url=http://www.queness.com/post/8567/create-a-dead-simple-twitter-feed-with-jquery]http://www.queness.com/post/8567/create-a-dead-simple-twitter-feed-with-jquery[/url]