共计 3100 个字符,预计需要花费 8 分钟才能阅读完成。
一个失常的申请: JSON
失常发申请时,curl
示例:
$ curl https://shanyue.tech/api/user?id=100
{
"id": 100,
"name": "shanyue",
"wechat": "xxxxx",
"phone": "183xxxxxxxx"
}
应用 fetch
发送申请,示例:
const data = await fetch('https://shanyue.tech/api/user?id=100', {
headers: {'content-type': 'application/json',},
method: 'GET',
}).then(res => res.json())
申请数据后,应用一个函数来解决数据
handleData(data)
一个 JSONP 申请
JSONP
,全称 JSON with Padding
,为了解决跨域的问题而呈现。尽管它只能解决 GET 跨域,尽管当初基本上都应用 CORS 跨域,但依然要晓得它,毕竟 面试会问。
curl
示例
$ curl https://shanyue.tech/api/user?id=100&callback=padding
padding({
"id": 100,
"name": "shanyue",
"wechat": "xxxxx",
"phone": "183xxxxxxxx"
})
对于失常的申请有何不同高深莫测: 多了一个 callback=padding, 并且响应数据被 padding 突围,这就是 JSONP
那申请数据后,如何解决数据呢?此时的 padding 就是解决数据的函数
window.padding = handleData
这里实现一个 jsonp 函数
function jsonp_simple ({url, onData, params}) {const script = document.createElement('script')
// 一、默认 callback 函数为 padding
script.src = `${url}?${stringify({ callback: 'padding', ...params})}`
// 二、应用 onData 作为 window.padding 函数,接收数据
window['padding'] = onData
document.body.appendChild(script)
}
此时会有一个问题: window.padding 函数会净化全局,如果有多个申请发送如何解决?
使 jsonp 的回调函数名作为一个随机变量,代码如下
function jsonp ({url, onData, params}) {const script = document.createElement('script')
// 一、为了防止全局净化,应用一个随机函数名
const cbFnName = `JSONP_PADDING_${Math.random().toString().slice(2)}`
// 二、默认 callback 函数为 cbFnName
script.src = `${url}?${stringify({ callback: cbFnName, ...params})}`
// 三、应用 onData 作为 cbFnName 回调函数,接收数据
window[cbFnName] = onData;
document.body.appendChild(script)
}
// 发送 JSONP 申请
jsonp({
url: 'http://localhost:10010',
params: {id: 10000},
onData (data) {console.log('Data:', data)
}
})
代码附录
残缺代码可见山月博客的 github 仓库: https://github.com/shfshanyue…
JSONP 实现残缺代码:
function stringify (data) {const pairs = Object.entries(data)
const qs = pairs.map(([k, v]) => {
let noValue = false
if (v === null || v === undefined || typeof v === 'object') {noValue = true}
return `${encodeURIComponent(k)}=${noValue ? '' : encodeURIComponent(v)}`
}).join('&')
return qs
}
function jsonp ({url, onData, params}) {const script = document.createElement('script')
// 一、为了防止全局净化,应用一个随机函数名
const cbFnName = `JSONP_PADDING_${Math.random().toString().slice(2)}`
// 二、默认 callback 函数为 cbFnName
script.src = `${url}?${stringify({ callback: cbFnName, ...params})}`
// 三、应用 onData 作为 cbFnName 回调函数,接收数据
window[cbFnName] = onData;
document.body.appendChild(script)
}
JSONP 服务端适配相干代码:
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)
const data = {name: 'shanyue', id: params.id}
if (params.callback) {str = `${params.callback}(${JSON.stringify(data)})`
res.end(str)
} else {res.end()
}
})
server.listen(10010, () => console.log('Done'))
JSONP 页面调用相干代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="./index.js" type="text/javascript"></script>
<script type="text/javascript">
jsonp({
url: 'http://localhost:10010',
params: {id: 10000},
onData (data) {console.log('Data:', data)
}
})
</script>
</body>
</html>
JSONP 实现代码示例演示
从中克隆代码: 山月博客的 github 仓库
文件构造
index.js
: jsonp 的简略与简单实现server.js
: 服务器接口模式demo.html
: 前端如何调用 JSONP
疾速演示
// 开启服务端
$ node server.js
// 对 demo.html 起一个服务,并且依照提醒在浏览器中关上地址,应该是 http://localhost:5000
// 察看控制台输入 JSONP 的回调后果
$ serve .
本文收录于 GitHub 日问: DailyQuestion,内含大厂内推机会、面经大全及若干面试题,每天学习五分钟,一年进入大厂中。
- 大厂面经大全
- 大厂内推
正文完
发表至: javascript
2020-12-18