什么是JSONP
JSONP的英文全称是 JSON with padding
值得注意的是这里的padding应当译作使用方式,因此JSONP应当译作——JSON的一种使用方式
JSONP的原理
由于同源策略,使得不同源的两个页面之间无法相互访问,然而HTML的script标签是个例外。利用这个特点,我们可以通过script标签来获取其它不同源网页的JSON数据——这种使用方式被称为JSONP
它的核心是绕过浏览器的同源策略
实现JSONP的方式
- 比如我们用script标签请求一些数据,假设请求用户定位的信息
<script src="http://http://www.bbwtest.com/users_location.json"></script>
问题在于,script标签会被当成js代码立即执行,但我们需要的是一些数据
所以,此时就需要后端的配合了
- 我们把script标签改一下,加上一些查询字符串
<script src="http://http://www.bbwtest.com/users_location.json?callback=showData"></script>
原本当后端收到这个请求时,我们希望得到一个{“name”:”bluesbonewong”,”age”:16}这种json类型的数据,但由于script标签会被当做js代码立即执行,所以我们希望后端收到请求后返回一个函数,如
showData({“name”:”bluesbonewong”,”age”:16})
那么此时前端只需要在数据返回前声明一个全局函数showData即可,如
function showData(data){
return data
}
实现代码
注意修改host文件使得不同域名映射至同一个IP地址,即可测试JSONP跨域
服务端代码
var http = require('http')
var fs = require('fs')
var path = require('path')
var url = require('url')
var server = http.createServer(function (request, response) {
var pathObj = url.parse(request.url, true)
console.log(pathObj)
switch (pathObj.pathname) {
case '/getdata':
var data = {"name": "bluesbonewong", "age": 16}
response.setHeader('content-type', 'text/json;charset=utf-8')
// 以下是重点
if (pathObj.query.callback) {
// 判断查询字符串中是否有callback
response.end(pathObj.query.callback + '(' + JSON.stringify(data) + ')')
// 返回一个 showData(JSON.stringify(data)) 函数
console.log(data)
// 这里data会被自动转换为对象格式{ name: 'bluesbonewong', age: 16 }双引号会被去除
// 所以一定要用JSON.stringify()把数据转换为json格式
} else {
response.end(data)
}
// 以上是重点
break
// 以下不用看
default:
fs.readFile(path.join(__dirname, pathObj.pathname), function (error, data) {
if (error) {
response.writeHead(404, 'not found')
response.end('<h1>not found</h1>')
} else {
response.end(data)
}
})
}
})
console.log('请在浏览器地址栏输入 localhost:8080')
server.listen(8080)
HTML代码
<!doctype html>
<html lang="ch">
<head>
<meta charset="utf-8">
<title>使用JSONP跨域</title>
</head>
<body>
<h1>JSONP实现跨域</h1>
<script>
// JSONP
function addScript() {
var script = document.createElement('script')
script.src = 'http://justfun:8080/getdata?callback=showData'
document.head.appendChild(script)
// 添加标签后会立即执行,且在数据到来之前,会阻断其它加载
document.head.removeChild(script)
// 移除也没关系,因为数据此时已经拿到
}
function showData(data) {
console.log(data)
}
addScript()
showData()
</script>
</body>
</html>
网友评论