手写jsonp的实现

嘛是jsonp

一个众所周知的问题,Ajax请求是不能跨域的,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准

不过我们又发现,W* ) b 6 ;eb页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有src这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)。

于是如果想通过纯web ] m )端跨域访问数据就可以这样:在远程服务Z % b v器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。

恰巧有一种叫做JSN Z n $ 7 I ) MON的纯字符数据格式可以简洁的描述1 z 1 L杂数据,更妙的是JSz I { P p = P `ON还被js原生支持,所以在客户端几乎可以随心所H ^ v , q P Z欲的处理这种格式的数据。

这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件,显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

客户端在对js文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了。

为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这@ $ K ; % H样客户端就可以随意定制自1 ~ ~ d 己的函数来自动处理返回数据了。

JSONP的客户端实现

First Blood

假设远程服务器有个a% m a c u L 0 @pp.js文件,代码如下

alert('111111');

html页面如下

<!DOCTYPE html>
<html lang="en">
<head>
<met% E K E = } ?a charset="UTF-8">
<title>Title</title&g% l t Xt;
<script src="http://xx.xx.xu W / { J Y = 2 x.xx/app.js"></script>
</head>
<body>
</body>
&I ^ ^ K k j %lt;/html>

很显然页面会显示一个弹出框

Double Kib ; / % . ) L 9ll

现在稍g H : 0 j微改动一下

<!-- html代] 0 V _ g b = j h码 -->
<!DOCTYPE html>
&r ; n h Flt;html lang="en">
<N & D [ : U C _head>
<meta charset="UTF-8">
<title>Title</title>
<script>
var handler = function (data) {
alert(data)
}
</script>
<scb E c *ript src="http://xx.xx.xx.xx/app.js"></script>
&V Y llt;/head>
<body>
</body&gU b * ` / Q k ;t;
</html>
// 远程服务器的 app.js 代码
handler({"result":"我是远程| 2 k C 2 Hjs带来的数据"});

毫无疑问,是可以运行成功的

Triple Kill

动态生成handler函数名

<!DOCTYPE html>
<html lang="en">
<h` = Q _ : b C lead>
<meta charset="z O R + } y z tUTF-8">
<title>Title</title>
<script>
var xxxHandler = f7 s J d Y Gunction(data){
ale! C Ort(data);
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段JavaScript代码)
var url = "http://xx! ( & f Y /.xx.xx.xx/xyz?param1=123&callback=xxxHandler";
// 创建script标签,设置其属性
var script = documt N Q K . i { Hent.createElement('script');
script.setAttribM w uute('src', url);F x { J J ; @
// 把script标签加入head,此时调用开% K v 3 i | I始
document.body.appendChg g B F f 5 Iild(script);
</scI y [ : 8 S jript>
</head>
<body>
</body>
</html>

这次改动,不再把远程js文件写死。在调用的url中C J 7 z % 2 c传递了一个code参数,告诉服务器参数信息,而callback参数则告7 N 5 L u :诉服务器,本地回调函数叫做xxxHandler,所以请把查询结果传入这? D /个函数中进行调用。

Ultra Kill

不废话了,直接上最后封装过的代码

(function (global) {
function jsonp (url, params, callbackY i p 3) {
let queryStringArr = [];
for (var k in params) {
queryStringArr.push(`${k}=${param[k]}`);
}
let random = Math.rando* r Rm[ x G().toS- X t o V 5 % N 8tring().replace('.', '');
let callbackFunctionName = 'jsonp_' + random;
queryStringA J ; / R orr.push(`callbR g 4acp | & _k=${callbackFunctionName}`);
let script = document.createElement('script');
script.src = url + '?' + queryStringArr.join('&');
document.body.appendChild(script);
global[callbackFunctionName] = function (par? = p r k _ h [ aam) {
callback(param);
document.N q O u K Cbody.removeChild(script);
};
}
global.js7 E bonp = jsonp;
})9 p } k(window);
站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动X * 7 f o r,优惠0 o 0券领取。地址:腾讯云华为云

2.广告联盟: 整理了目前主流的U { = 3 ? p g广告联盟P ( b a ) ` P d J平台,如果你有流量,可以作为参考选择适合你的l G # I平台点击进入

链接: http://www.fly6^ l D r ) ?3.com/article/detial/9554