前言:
为尽可能保证浏览器端安全,浏览器会遵循SOP协议,即同源协议
ajax无法完成跨域请求
$.get $.post $.ajax都不可以
jsonp作为ajax的一种扩展协议可以完成跨域请求
$.getJson()也可以完成跨域请求(当然不跨域也可以)
日常开发中会经常遇到前端跨域访问请求数据的场景
比如
www.server.com
img.server.com
当用户在www下浏览时需要获取指定记录id的图片,则我们需要在www的域下请求img域下的数据,常规情况下浏览器会处于安全控制限制无法完成跨域请求,但页面中的script或iframe标签是可以载入跨域请求的(link img也可以)
实现方式:
===============================================================
服务端
看网上很多讲跨域的都只是说了下前端如何编码,对后端的处理只字未提,虽然后端的处理很简单,但后端的处理才是点睛之笔,返回一个前端的调用函数语句,这就是传说中的回调函数
<?php
if (isset($_GET['callback'])) {
$callback = $_GET['callback'];
$resultArr = [];
$resultArr['id'] = $_GET['id'];
$resultArr['img'] = "http://img.server.com/upload/img/201511031319.png";
$resultJson = json_encode($resultArr);
//callback({id:1, img:....}) 组装成调用js函数的格式 客户端载入自然触发其本地定义的回调函数
echo $callback . "({$resultJson})";
exit();
} //因为是被script标签请求载入的,所以返回的数据会包在script中,自然就触发了callback函数
===============================================================
1、JS script方式
其实原理很简单
1、在当前域下我定义一个函数作为回调函数
2、组建一个script标签元素节点,设置src为跨域请求的某API的url地址,同时此url地址中务必填写上回调函数名参数
3、将script标签挂载到文档流中,会跨域请求载入,变相的访问了跨域API,触发了API的方法,返回的数据被填充到script标签中,如果返回的是一个当前域下定义好的函数,那自然就触发处理相关数据了
4、跨域完成
在www下定义回调函数callback
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="http://www.yii.com/a.js"></script>
</head>
<body>
<button onclick="request()">click here</button>
<script type="text/javascript">
//回调函数callback定义
//服务端输出的数据为 callback({key1:data1, key2;data2}) 到本页面 即调用此定义好的函数
function callback(json) {
for (i in json) {
alert(i + ":" + json[i]);
}
if (json.tagId) {
var tagId = document.getElementById(json.tagId);
tagId.parentNode.removeChild(tagId);
}
}
//发起跨域请求
function request() {
//利用script标签可跨域访问的特性
var script = document.createElement('script');
script.id = Math.random();
script.type = 'text/javascript';
//跨域 将callback函数名称传递给跨域服务器 服务端利用此函数名组建
script.src = "http://img.server.com/index.php?callback=callback&id=1&tagId=" + script.id;
//将可跨域请求的script标签挂载到head标签上
document.getElementsByTagName("head")[0].appendChild(script);
}
</script>
</body>
</html>
===============================================================
2、jsonp方式
jsonp是ajax的扩展,严格的说它已经不是ajax,只是复用ajax的某些控制流程,封装我们上面说的js方式
重点:
dataType:'jsonp' //指定使用jsonp方式
jsonp:'callback' //回调函数的键名 传递给服务器时服务器通过此键名获取应该返回调用的函数名
jsonpCallback:'myCallback' //回调函数名不随机,自定义一个
<script type="text/javascript" >
//其实jquery会组合成这样的请求
//http://img.server.com/index.php?callback=myCallback&id=1
$.ajax({
async: false,
type: 'get',
url: "http://img.server.com/index.php?id=1",
//指定为jsonp方式
dataType: 'jsonp',
//回调函数的键值名,即服务端通过此键值访问传递的回调函数名
jsonp: 'callback',
//回调函数名,若不指定则jquery会随机生成一个
jsonpCallback: 'myCallback',
success: function(result) {
for (var i in result) {
alert(i + ":" + result[i]);
}
},
timeout: 3000
});
//Jquery会根据你指定的jsonpCallback参数在本地生成一个
//function myCallback(result) {
//这样就调用了success方法
//this.success(result);
//}
</script>
===============================================================
3、getJSON
重点:
一定要在url中写上callback=?,只有这样才会在本地生成一个回调函数,跨域的后端通过callback获取到此函数名,进行回调
<script type="text/javascript" >
//其实jquery会组合成这样的请求
//http://img.server.com/index.php?callback=myCallback&id=1
var url = "http://img.server.com/index.php?callback=?"; //记住一定要有callback=?
var data = {'id':1};
$.getJSON(
url,
data,
function(result){
for (var i in result) {
alert(i + ":" + result[i]);
}
});
</script>
===============================================================
来源:oschina
链接:https://my.oschina.net/u/252076/blog/528813