jsonp 原理

2014年5月13日

本文写于 2014 年。如今跨域更常见的做法是 CORS;JSONP 仅作历史与兼容理解。

工作中少不了跟 ajax 打交道,本着少造轮子的思想,一般都是使用 jquery 的 ajax 接口,同域的 ajax 大家都知道是通过 xhr(XMLHttpRequest) 请求完成, 在 jquery 中,jsonp 请求也是调用的 ajax 接口,只是传递的参数不同,而其实跨域的 jsonp 请求其实根本是不同的概念,jsonp 根本就没有使用到 xhr 请求。

xhr 由于同源策略限制的原因,是无法跨域的。jsonp 请求其实是在网页中动态的创建了一个 script 请求,这样就相当于创建了一个 GET 请求,就不会受到跨域的限制,例如在域名 abc.com 向 api.abc.com 发起一个 jsonp 请求,其实是在页面中动态添加

1<script src="http://api.abc.com"></script>

稍微封装下应该是这样的:

12345function jsonpRequest(url) {  var script = document.createElement("script");  script.src = url;  document.getElementsByTagName("body")[0].appendChild(script);}

那如何传递参数,和获取服务器返回的数据呢?传递参数很好解决,直接 url 传参就行了,而获取服务器返回的数据则需要服务器作一定的处理,这里服务器需要返回的并不是 json 数据,而是一个 js 的回调方法的调用,例如 jsonCallback({code:0}), 而这个回调函数则需要我们在页面中定义。

123function jsonpCallback(data) {  console.log(data.code);}

这样,script 请求完成后会直接执行服务器返回的回调方法,也就是我们这里定义的方法。

实际上我们的页面上可能会有不止一个 jsonp 的请求,为每个单独请求定义一个回调方法可能比较麻烦,后端的同学也可能会抱怨为每个接口定义指定的调用方法很麻烦,其实我们可以把回调的方法名作为参数传递给后端,而回调方法我们也能通过随机数生成(jquery 的做法)

12345678910var jsonpCallbackNum = 1;function jsonpRequest(url, callback) {  jsonpCallbackNum++;  var randomCallback = "jsonpcallback" + jsonpCallbackNum;  window[randomCallback] = callback;  var script = document.createElement("script");  spliter = url.indexOf("?") !== -1 ? "&" : "?";  script.src = url + spliter + "jsoncallback=" + randomCallback;  document.getElementsByTagName("body")[0].appendChild(script);}

恩,实现起来也并不是很难,但我这写得只是 demo,实际的业务中可能还要根据需求定义上面的代码。

评论

0 条讨论

匿名评论需填写昵称、邮箱,并通过人机验证。邮箱不会公开展示,提交后需审核通过才会显示。

还没有评论,来抢沙发吧。