方法一:jsonp
1. 概念
由于link、img、script等标签的src属性可以实现跨域请求,所以一般前端会使用script来接收后端返回的函数执行。具体步骤如下:
- 后端返回一个函数执行,比如函数名是cb,函数执行的传入参数是一个对象{a:1},即cb({a:1})
- 前端js脚本定义好一个跟函数执行同名的函数cb以及形参params,这个params其实就是我们要得到的数据
- 利用script的src属性值为请求的url,并插入到dom中,这样相当于用src属性想后端请求,请求回来的数据插入到了这个script脚本中。
- 一插入即调用了cb函数,而cb是我们定义好的函数,所以我们定义的cb中的参数就是我们要的数据。
这样说来还是比较抽象,一起用代码来看下如何实现:
2. 代码层面实现jsonp
- 首先,我们假定向后端请求的地址是’https://www.baidu.com/s?wd=jsonp&cb=show’,并且知道(或约定)后端返回的数据是’show({wd:“jsonp”,p:false,s:[“jsonp”,“jsonp跨域”,“jsonp实现”]})’
- 那么我们就需要定义一个show方法
<script type="text/javascript">
function show(data){
console.log(data);//这就是我们需要的数据
}
</script>
- 然后,我们要准备script标签,并且src为上述假定的url,并且按需插入这个script
<script type="text/javascript">
function show(data){
console.log(data);//这就是我们需要的数据
}
let srcipt = document.createElement('script');
script.src = 'https://www.baidu.com/s?wd=jsonp&cb=show';
document.body.append(script);//一插入即请求,请求就相当于执行了show这个函数,那么show函数是上面定义的,所以就得到了data
</script>
3. 将jsonp方法封装成一个方法
- 在看以下方法之前,要注意在创建script后,插入到dom中,得到数据以后,应该及时将script这个dom移出。
function jsonp({url,params,cb}){
return new Promise((resolve,reject) => {
//创建script标签
let script = document.createElement('script');
//要全局下调用这个函数,所以可以挂在在window上
window[cb] = function(data){
resolve(data);
document.body.removeChild(script);//
}
//将params拼接
let paramsStr = '';
params = {...params,cb};
for(let attr in params){//wd=jsonp&cb=show
paramsStr += `${attr}=${params[attr]}&`;
}
paramsStr = paramsStr.slice(0,paramsStr.length - 1);
script.src = `${url}?${paramsStr}`;
document.body.append(script);
})
}
jsonp({
url:'https://www.baidu.com/s',
params:{wd:'jsonp'},
cb:"show"
}).then(data => {
console.log(data);
})
jsonp的缺点
- 缺点:
- 只能发送get请求,不支持post put delete
- 不安全,容易造成xss攻击,原因:
- 去请求别的域,得到别的域返回的数据,万一是个脚本,那就注入到自己的代码里了。
- 现在基本不采用了。
实现跨域的9种方法(点击可跳转详情页面)
- jsonp
- cors
- postMessage
- document.domain
- window.name
- location.hash
- http-proxy 后续会有详细文章阐述
- nginx 后续会有详细版块阐述
- websocket