jsonp是什么
jsonp和json
json是一种轻量级的数据传输格式,一般被用于web应用中,大部分前后端分离的应用都以json格式进行数据传输。
jsonp主要用来解决跨域访问的问题,是一种常见的网络请求方式。
因为ajax直接请求普通文件会存在跨域无权限访问的问题,但是web页面中可以调用js文件,所以解决跨域问题的核心在于通过<script>
标签的src来帮助我们请求数据,将请求到的数据当做一个JavaScript的函数来执行,并且在执行的过程中传入我们需要的json,所以封装jsonp的核心在于我们监听window上的jsonp进行回调时的名称。
如何使用jsonp
1.web页面可以无条件执行跨域js文件中的代码(符合web脚本安全策略的)
假设远程服务器remoteserver.com的根目录下有个remote.js代码如下:
alert('我是远程文件返回数据');
在本地服务器中有个local.html文件页面代码如下:
<head>
<title></title>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
页面执行时将会弹出一个窗体,显示跨域成功。
2.现在在local.html页面定义一个函数,然后在remote.js中传入数据进行调用
本地local.js页面代码如下所示:
<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
远程remote.js的文件代码如下:
localHandler({"result":"我是远程js的数据"});
运行之后就可以查看到本地的函数被跨域的远程js调用,并且还可以接收到远程js的数据,接下来我们就要解决远程js如何知道它应该调用哪个本地函数。
3.所以服务端提供的脚本需要是动态生成的,调用者可以传一个参数过去告诉服务端需要调用哪段函数并返回,这样服务器就可以按照客户端的需求来生成js脚本并响应
接下来给个例子,如local.html页面的代码:
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
这段代码在调用的url中传递一个code参数,告诉服务器需要查的航班为CA1998,而callback函数则告诉服务器,我的本地回调函数为flightHandler,所以可以把查询结果传入这个函数中进行调用。
4.接下来就是如何把代码进行封装,用于与用户界面进行交互,从而实现多次重复调用
<script>
let count = 1
export default function originJSONP(option) {
// 从传入的option中提取url
const url = option.url
// 在body中添加script标签
const body = document.getElementsByTagName('body')[0]
const script = document.createElement('script');
// 在内部产生一个不重复的callback
const callback = 'jsonp' + count++
// 监听window上的jsonp调用
return new Promise((resolve, reject) => {
try {
window[callback] = function (result) {
body.removeChild(script);
resolve(result)
}
const params = handleParam(option.data);
script.src = url + '?callback'+callback
body.appendChild(script)
} catch (e) {
body.removeChild(script)
reject(e)
}
})
}
function handleParam(data) {
let url = ''
for (let key in data) {
let value = data[key] !== undefined ? data[key] : ''
url += `&${key}=${encodeURIComponent(value)}`
}
return url
}
</script>
关于ajax和jsonp的异同:
1.ajax和jsonp在调用方式上相似,都是请求一个url,然后把服务器返回的数据进行处理
2.但ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加script标签调用服务器提供的js脚本
ajax的底层是用XmlHttprequest类来实现异步请求(不刷新页面就可以获得响应数据),所以不能跨域。
他们的区别也不在于是否可以跨域,ajax通过服务端代理也可以跨域,jsonp也可以进行同域的数据获取。
文章参考于https://blog.csdn.net/HansExploration/article/details/80314948