WEB前端跨域知识总结—JSONP
2017-11-06 本文已影响297人
108N8
一、前言
- 初识
timg.jpgXMLHttpRequest cannot load xxxx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'xxxx' is therefore not allowed access. The response had HTTP status code 404.
-
什么跨域?
简述:由于浏览器XMLHttpRequest同源策略(域名、端口、协议必须全一致)影响,禁止使用XHR对象向不同源服务器发起HTTP请求。 -
为啥禁止跨域?
简述:AJAX(XMLHttpRequest)同源策略主要用来防止CSRF攻击。我们发起的每一次HTTP请求都会带上请求地址对应的cookie,简单来说就是“模仿用户”访问“目标网站”。 -
如何解决跨域?
简述:解决跨域问题的方案有很多,例如JSONP、CROS、反向代理等等。 - 今天我们就一起学习下,JSONP跨域解决方案的具体原理,以及实现封装一个自己的jsonp.js。
二、JSONP
大家都知道页面中,图片(img)是可引用外部的,js脚本文件(script)也可引入外部的,所以基本原理就是通过动态创建script标签,然后利用src属性进行跨域。
1. 基本原理
<body>
<script>
function fn1(str) { alert('我是fn1:'+ str) }
</script>
<script>
fn1('下面调用')
</script>
</body>
总结:上面代码想必大家都知道结果吧。会弹出“我是fn1:下面调用”
2. 百度搜索api简单使用
百度搜索的接口: https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=abc&cb=show
<script>
function fn1(url){
window.show = function(json){
console.log(json);
}
var oS = document.createElement('script');
oS.src = url;
document.head.appendChild(oS);
}
fn1('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=abc&cb=show');
</script>
结果如下图所示
总结:从上图我们可以看出“abc”关键字的搜索结果可以展示了。也就是解决了跨域问题。
遗留问题:
- 创建的script标签,用完是不是需要删除?
- 关键字(此处搜索内容)是不是可以灵活进行自定义?
- 等等
JSONP方法完善以及封装
function json2url(json){
var arr = [];
for(var name in json){
arr.push(name+'='+json[name]);
}
return arr.join('&');
}
/*
** @jsonp jsonp跨域交互
** @params
** [object]
*/
function jsonp(json){
//参数初始值
json = json||{};
if(!json.url)return;
//回调名字
json.cbName = json.cbName||'cb';
//超时时间(ms)
json.timeout =json.timeout||15000;
//提交数据
json.data = json.data||{};
//回调函数的名字(解决了缓存问题)
json.data[json.cbName] = 'show'+Math.random();
//把回调函数名字中的.去掉。
json.data[json.cbName] = json.data[json.cbName].replace('.','');
//网络超时
json.timer = setTimeout(function(){
window[json.data[json.cbName]] = function(){
oHead.removeChild(oS);
json.error&&json.error('亲,网络不给力');
};
},json.timeout);
//定义回调函数(全局的)
window[json.data[json.cbName]] = function(result){
//把网络超时干掉
clearTimeout(json.timer);
//需要把script删除
oHead.removeChild(oS);
//执行成功回调函数
json.success&&json.success(result);
};
//获取head标签。
var oHead = document.getElementsByTagName('head')[0];
//动态创建script
var oS = document.createElement('script');
//给script加src
oS.src = json.url+'?'+json2url(json.data);
//把script插入到head标签中
oHead.appendChild(oS);
}