什么是JSONP
JSONP的英文全稱是 JSON with padding
值得注意的是這里的padding應(yīng)當(dāng)譯作使用方式圈膏,因此JSONP應(yīng)當(dāng)譯作——JSON的一種使用方式
JSONP的原理
由于同源策略蠢络,使得不同源的兩個頁面之間無法相互訪問桦山,然而HTML的script標(biāo)簽是個例外。利用這個特點膀捷,我們可以通過script標(biāo)簽來獲取其它不同源網(wǎng)頁的JSON數(shù)據(jù)——這種使用方式被稱為JSONP
它的核心是繞過瀏覽器的同源策略
實現(xiàn)JSONP的方式
- 比如我們用script標(biāo)簽請求一些數(shù)據(jù)尽狠,假設(shè)請求用戶定位的信息
<script src="http://http://www.bbwtest.com/users_location.json"></script>
問題在于,script標(biāo)簽會被當(dāng)成js代碼立即執(zhí)行严卖,但我們需要的是一些數(shù)據(jù)
所以,此時就需要后端的配合了
- 我們把script標(biāo)簽改一下布轿,加上一些查詢字符串
<script src="http://http://www.bbwtest.com/users_location.json?callback=showData"></script>
原本當(dāng)后端收到這個請求時哮笆,我們希望得到一個{“name”:”bluesbonewong”,”age”:16}這種json類型的數(shù)據(jù),但由于script標(biāo)簽會被當(dāng)做js代碼立即執(zhí)行汰扭,所以我們希望后端收到請求后返回一個函數(shù)稠肘,如
showData({“name”:”bluesbonewong”,”age”:16})
那么此時前端只需要在數(shù)據(jù)返回前聲明一個全局函數(shù)showData即可,如
function showData(data){
return data
}
實現(xiàn)代碼
注意修改host文件使得不同域名映射至同一個IP地址萝毛,即可測試JSONP跨域
服務(wù)端代碼
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)) 函數(shù)
console.log(data)
// 這里data會被自動轉(zhuǎn)換為對象格式{ name: 'bluesbonewong', age: 16 }雙引號會被去除
// 所以一定要用JSON.stringify()把數(shù)據(jù)轉(zhuǎn)換為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實現(xiàn)跨域</h1>
<script>
// JSONP
function addScript() {
var script = document.createElement('script')
script.src = 'http://justfun:8080/getdata?callback=showData'
document.head.appendChild(script)
// 添加標(biāo)簽后會立即執(zhí)行项阴,且在數(shù)據(jù)到來之前,會阻斷其它加載
document.head.removeChild(script)
// 移除也沒關(guān)系笆包,因為數(shù)據(jù)此時已經(jīng)拿到
}
function showData(data) {
console.log(data)
}
addScript()
showData()
</script>
</body>
</html>