本文详解JSONP技术如何利用script元素的src属性发起HTTP GET请求,从而绕过浏览器的同源策略限制。通过动态创建script节点并指定回调函数名,服务器返回包裹在函数调用中的JSON数据,客户端解析执行后获取数据。文章提供了完整的JavaScript实现代码,包括动态生成唯一回调名、拼接URL参数及清理资源等关键步骤。
JSONP跨域原理与实现:利用script标签绕过同源限制
script元素的src属性可以设置URL并发起HTTP GET请求。利用script元素进行脚本操作,可以实现跨域通信,且不受同源策略的限制。在使用基于script的Ajax传输协议时,服务器响应通常采用JSON编码的数据格式。当脚本执行时,JavaScript解析器会自动对其进行解码。由于使用了JSON数据格式,这种Ajax传输协议被称为“JSONP”。因此,使用JSONP技术时,只需设置script的src属性,并将其插入到document中,浏览器便会发送HTTP请求以下载src属性所指向的URL。
JSONP响应格式要求
当使用script元素调用数据时,响应内容必须用JavaScript函数名和圆括号包裹起来(即只能作为函数的参数),而不能是直接的一段JSON数据。
代码如下:
response(
[1, 2, {"hello", "world"}]
) 服务器端处理与回调函数指定
为了确保可行性,我们需要通过某种方式告知服务器,当前请求来自script元素,因此服务器必须返回JSONP响应而非普通JSON。这可以通过在URL中添加查询参数来实现,例如追加“?json”或“&json”。
在实际应用中,支持JSONP的服务通常不会强制指定客户端必须实现的回调函数名称(如response)。相反,它们使用查询参数的值,允许客户端指定一个函数名,然后服务器使用该函数名填充响应内容。
JavaScript实现代码详解
代码如下:
//根据指定的url发送一个json请求
//然后把解析得到的响应数据传递给回调函数
//在url中添加一个名为jsonp的查询参数, 用于指定该请求的回调函数的名称
function getJSONP(url, callback){
//为本次请求创建一个唯一的回调函数名称
var cbnum = "cb"+getJSONP.counter++;
var cbname = "getJSONP."+cbnum; //作为jsonp函数的属性
//将回调函数名称以表单编码的形式添加到url查询部分中
if(url.indexOf("?") === -1){
url += "?jsonp="+cbname;
}else{
url += "&jsonp="+cbname;
}
//创建<script>用于发送请求
var script = document.createElement("script");
//定义被脚本执行的回调函数
getJSONP[cbnum] = function(response){
try{
callback(response); //处理响应
}
}finally{
//删除该函数, 并移除相应script元素
delete getJSONP[cbnum];
script.parentNode.removeChild(script);
}
}
//立即触发http请求
script.src = url;
document.body.appendChild(script);
}
getJSONP.counter = 0;