jsonp步骤_JSONP的实现流程

在进行AJAX的时候会经常产生这样一个报错:

6bb94dea8ac4a8f59f1008665ea1d3a0.png

看红字,这是浏览器的同源策略,使跨域进行的AJAX无效。注意,不是不发送AJAX请求(其实就是HTTP请求),而是请求了,也返回了,但浏览器‘咔擦’一声,下面没有了。对比下fiddler和浏览器抓的包的异同:

fiddler:

377786c80af5edf126688917aa007027.png

chrome:

bbe62a9683d81dae7b50bc02c32a0d42.png

039a3bfbdf3fc95433536cca7f1691f0.png

简而言之,浏览器这边就是头(response header)给看,身体(response body)不给看。

什么是同源策略?为什么会有同源策略?这一点在吴翰清老师著的《白帽子讲Web安全》一书中由阐述,这里就不赘述了。下面要做的,就是使用JSONP让上面的报错消失,按正确的流程进行下去。

首先介绍下我这里的环境,两个Web服务器,Tomcat监听8081,Node监听3000,Tomcat这边实现一个处理AJAX的JSP文件,很简单,返回一个JSON

{"status": true}

Tomcat的页面对这个URL发出AJAX请求,并打印出了返回值

52c0b792a0c8fc956cdbe1e4e6ab72d1.png

但Node的页面发出AJAX请求,则像上面那样报错了,因为AJAX有同源策略保护。怎么绕过这个保护呢?平时我们页面引入的CSS、JS可能是从其他的服务器比如静态服务器、CDN获取内容,都在不同的域,可知页面内的标签引入JS是没有同源策略一说的,而且也是进行request和处理response,于是我们把这个AJAX请求改为如下代码:

var script = document.createElement('script');

script.src= 'http://localhost:8081/test/true.jsp';

document.body.insertBefore(script, document.body.lastChild);

但还是残忍的报错了

a60bafac16c31905dd10ac722f47c796.png

因为返回的JSON({"status": true})成为了一个独立的js片段,而这个片段明显是不符合语法的,如果返回的是符合语法规范的处理JSON的js片段而不仅仅是JSON就好了。比如我们将服务器端的代码改成这样:

console.log({"status": true});

再在Node的页面进行AJAX

a21d934f4c42ecc609f7fbcd84b631d3.png

目的是达到了,但问题是,这个AJAX的servlet不仅返回了数据,还返回了行为,难道我要把处理DOM的js写在这里面吗?页面重构了又跑到这里来修改?问题太美不敢想,所以请求成功的方法必须写在页面的js里面,比如这样

functioncallback(data) {

console.log(data);

}var script = document.createElement('script');

script.src= 'http://localhost:8081/test/true.jsp';

document.body.insertBefore(script, document.body.lastChild);

而服务器返回的js片段直接调用这个function就行了,这个就叫回调函数了

callback({"status": true});

可以看到,这个方案比之前好多了,servlet和请求页面的耦合度低了很多,但没完全解决,比如callback这个回调函数的名字,如果把这个名字放在请求的parameter中,比如这样

functioncallback(data) {

console.log(data);

}var script = document.createElement('script');

script.src= 'http://localhost:8081/test/true.jsp?cb=callback';

document.body.insertBefore(script, document.body.lastChild);

服务器对这个parameter进行处理

({"status": true});

优化一下,对没有cb参数的请求仅返回JSON

response.setContentType("application/json; charset=utf-8");%>{"status": true}

response.setContentType("application/javascript; charset=utf-8");%>

({"status": true})

那么整个JSONP的功能就实现了。但还有一点瑕疵,代码执行完html中留下了一个script标签,强迫症能忍?处女座能忍?

解决方法:可以使用jQuery的方法,jQuery会清除掉留下的script标签。

$.ajax({

url:'http://localhost:8081/test/true.jsp',

dataType:"jsonp",

jsonp:"cb",

success:function(data) {

console.log(data)

}

});

也可以自己实现一个,我抛个砖,在js加载完成后删除节点。

functioncallback(data) {

console.log(data);

}var script = document.createElement('script');

script.src= 'http://localhost:8081/test/true.jsp?cb=callback';

document.body.insertBefore(script, document.body.lastChild);

script.οnlοad= function(){this.parentNode.removeChild(this);

};

至此,不知道有人发现没有,JSONP这种方式有一个致命的缺陷:就是由于它是通过引入script节点实现的,所以只支持GET方法。如果你任性,你无理取闹,你一定要用post跨域,那么只能考虑使用CORS了。

JSONP的东西就到此结束了,其实做完才发现,实际上这是个很简单的概念,取了个比较唬人的名字而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值