跨域解决方案之JSONP实现
本文阅读时长:1分钟不到
前端面试,那可是经常问到同源策略和跨域这问题啊
解决跨域的其中一种方式那必离不开JSONP,想必大伙随口都能答上来
那万一面试要手写JSONP实现时,如何写出让面试官眼前一黑的代码呢?
Webpack的异步加载模块也用到了JSONP哦
何为同源、跨域
同源就是"协议+域名+端口"三者都相同,其他没必要逼逼那么多。
同源策略会有如下限制范围:
- Cookie、LocalStorage 和 IndexDB
- DOM 无法获得
- AJAX发送过去,在数据从后端返回的路上被浏览器拦截了
JSONP原理
<script>
标签的请求不被阻止,很多带有src
属性的标签都不会组织,例如<img>
。但是这些标签发起的请求都是GET,所以jsonp也只支持GET请求。
同时后端要响应的数据可以用回调函数名包裹成JavaScript,这时就得小心XSS攻击了:
// 这是一串js,回调函数的名字是'callback',回调函数的参数就是'hello,world!'
result = "callback" + "('hello,world')";
JSONP实现
直接贴上一个HTML代码,方便运行,测试接口也是可以用滴。
不要问我为什么那么贴心又细致,因为我也是小白哈。。。要是有缺陷和其他问题,欢迎指出和讨论
百看不如一敲。敲!立马的!
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>jsonp详细实现带注释</title>
<script>
function jsonp(url, params, callback = null) {
// 函数调用计数,每次调用该函数时自增,避免回调函数重名
const cb_count = ++jsonp.cnt || (jsonp.cnt = 1)
const callbackName = callback || ('cb_' + cb_count)
// 向URL后面拼接请求参数和回调函数名
let querystring = (url.indexOf("?") > 0 ? '&' : '?') + (`callback=${callbackName}`)
Object.entries(params || {}).forEach(([k, v]) => querystring += (`&${k}=${v}`))
// 创建script标签、添加src属性并添加到body中
const scriptTag = document.createElement('script')
scriptTag.src = url + querystring
document.body.appendChild(scriptTag)
return new Promise((resolve, reject) => {
window[callbackName] = (data) => {
resolve(data)
scriptTag.remove()
delete window[callbackName]
}
})
}
</script>
</head>
<body>
<h2> JSONP的实现流程</h2>
<ul>
<li>声明回调函数,函数名(jsonp)作为API的请求参数,函数形参为要获取的数据</li>
<li>创建一个<script>标签,src="api接口",附加上函数名e.g: ?callback=jsonp</li>
<li>后端判断是jsonp的请求,则把数据和回调函数名进行拼接e.g: "jsonp('Merry Christmas ')"</li>
<li>后端把拼接后的字符串返回,它将被作为<script>标签的脚本被浏览器执行</li>
</ul>
</body>
<script>
jsonp('https://api.asilu.com/php/web-info.php?url=https://www.qq.com/&jojo=6').then(data => {
console.log(data)
})
jsonp('https://api.asilu.com/php/web-info.php', {
url: 'https://v.douyin.com/'
}).then(data => {
console.log(data)
})
jsonp('https://suggest.taobao.com/sug', {
code: 'utf-8',
q: '脆脆鲨'
}).then(data => console.log(data))
</script>
</html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端