JSONP,全称JSON with Padding
。为解决 GET 请求跨域。
跨域常用方案:CORS
。
JSONP 基于两个原理:
- 动态生成
script
,使用script.src
地址来跨域; script.src
加载的脚本内容为 JSONP:即 PADDING(JSON) 格式。
注意:在 GET 的 URL 中,查询参数包含callback
,callback
值是一个方法,方法的 形参 就是获取到的服务端数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简单 JSONP </title>
</head>
<body>
<input type="text">
<button onclick="handleSend()">Send</button>
<ul class="main">
</ul>
<script src="./index.js"></script>
<script>
function handleData(res) {
const liEl = document.createElement('li')
liEl.innerText = res.msg
const ulEl = document.getElementsByClassName('main')
ulEl[0].appendChild(liEl)
const inputEl = document.getElementsByTagName('input')
inputEl[0].value = ''
}
function handleSend() {
const inputEl = document.getElementsByTagName('input')
const sendData = { id: Math.floor(Math.random() * 10), msg: inputEl[0].value || '' }
jsonp({
url: 'http://127.0.0.1:10010',
params: sendData,
onData: handleData
});
}
</script>
</body>
</html>
function stringify(params) {
const obj = Object.entries(params)
const qs = obj.map(([k, v])=> {
let noVal = false
if(v === null || v === undefined || typeof v === 'object') {
noVal = true
}
return `${encodeURIComponent(k)}=${noVal ? '' : encodeURIComponent(v)}`
}).join('&')
return qs
}
function jsonp({url, onData, params}) {
const scriptEl = document.createElement('script')
// 1.函数随机名称,避免全局污染
const cbFnName = 'JSONP_PADDING' + Math.random().toString().slice(2)
// 2.默认 callback 为 cbFnName
scriptEl.src = `${url}?${stringify({ callback: cbFnName, ...params })}`
// 3.使用 onData 作为回调函数,接收服务端响应数据
window[cbFnName] = onData
document.body.appendChild(scriptEl)
}
const http = require('http');
const url = require('url');
const qs = require('querystring')
const server = http.createServer((req, res) => {
const {pathname, query} = url.parse(req.url)
const params = qs.parse(query)
console.info('params', params)
const data = {msg: params.msg, id: params.id}
if(params.callback) {
const str = `${params.callback}(${JSON.stringify(data)})`
res.end(str)
} else {
res.end()
}
})
server.listen(10010, () => console.info('server.....'))