前端跨域方案有很多种,这次介绍的是JSONP。
一、什么事跨域
受浏览器的同源策略的约束,访问不同的域名加协议、端口(三者任意一个不同)的资源将会照成跨域问题。
二、JSONP
JSONP,JSON with Padding(填充式json或参数式json的缩写),是 json 的一种”使用模式”。
由于<script>标签不受同源策略的约束,它可以载入任意地方的 JavaScript 文件,而jsonp就是利用的这一缺陷。他的基本原理就是通过动态创建<script>标签,然后把src指向服务端地址,而这个地址后面跟个参数callback=***,服务端在返回数据时,在***放置一个方法,相当于在前端执行***这个方法,所以在请求前我们需要给window绑定这个方法。
三、实现
客户端
如果直接进入页面后就要进行跨域,可以直接写HTML元素:
<script> function jsonpCallback(data) { console.log(data); } </script> <script src="http://127.0.0.1:8088/jsonp?callback=jsonpCallback" type="text/javascript"></script>
要注意的是jsonpCallback要先定义,否则会执行该函数出错。
或者我们可以动态的创建<script>标签,并添加到页面中的方式加载:
<script type="text/javascript"> function startJsonp() { var script = document.createElement('script'); script.src = 'text/javascript'; script.src = 'http://127.0.0.1:8088/jsonp?callback=jsonpCallback'; document.body.appendChild(script); } function jsonpCallback(data) { console.log(data); } startJsonp(); </script>
当然,这两种方式没有本质的区别。
服务端
后端使用NodeJS实现:
var http = require('http'),url = require('url'),querystring = require('querystring'),server = http.createServer(); // request请求 server.on('request',function(req,res){ var urlPath = url.parse(req.url).pathname; var qs = querystring.parse(req.url.split('?')[1]); if (urlPath === '/jsonp' && qs.callback){ res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'}); var data = { "hello": "world" }; data = JSON.stringify(data); var callback = qs.callback+'('+data+');'; res.end(callback); } }).listen(8088);
当请求的路径是/jsonp时,我们会去将callback和数据返回给浏览器,而浏览器则会调用window下的该方法,所有我们可以在控制台上看到打印的数据。
JSONP用起来的话,其实也是很简单的,且对于信任的域,这样调用资源也是很方便的。需要注意的是JSONP只支持GET请求,不支持POST请求。