杂谈 -JSONP 探索
前言
平时工作当中,也已经很久没有用 JSONP 来跨域请求了,现重新整理一下,写出自己对 JSONP 的理解。如果写的有不对的,请各位看官评论指出,感谢。
行文时,系统环境为 macOS Mojave v10.14.5,开发工具为 vscode 1.45.1,浏览器为 Goolge Chrome 版本 81.0.4044.138 。
JSONP是什么
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。
这是引用了百度百科对 JSONP 的定义。笔者自己的理解是, JSONP 是一种利用浏览器 script 标签的能力实现访问跨域数据的小技巧。就是利用 script 标签能访问跨域资源的能力,利用 JSON 去填充返回内容,以达到跨域的目的。
JSONP解决了什么问题
上文说到了,JSONP 解决了跨域问题。那啥是跨域呢,简单说就是发起请求的网站与被请求的网站,它俩的协议、主机、端口不是完全一样的。表现就是,跨域时,请求是不会成功的。
JSONP 到底是怎么实现的呢,笔者的理解是,基于下面三点实现的:
浏览器的 script 标签不受同源策略的限制,可以请求到其它源的资源。
当 script 标签请求的资源拿到后,会被浏览器的 JS引擎 执行。
script 请求到的资源是在 全局上下文 里执行的。
JSONP测试
接下来就写点代码测试一下,并用大白话把过程描述一下。
用koa模拟服务端,代码如下
前端代码如下
笔者认为的过程如下:
服务端接收到 /jsonp 这个路由的请求时(当然了,是get请求),就返回一段文本,内容是一个 `console.log(1)` 和一个函数调用,在这个调用里传入 "这是服务端的内容" 。对于服务端来说,这一段始终是字符串文本。
前端在把 script 标签塞入到文档后,这个 script 就开始请求,请求拿到后是 `console.log(1);handler("这是服务端的内容")` 这样的内容,然后浏览器 JS引擎 就把这段内容执行,可以对应 eval() 理解。执行的时候,是处于 全局上下文 的。所以是能拿到 handler 这个函数的。然后呢,在 handler 里就通过 res 拿到了服务端传回给前端的内容。是不是很妙?!!我第一次用的时候,真的是眼前一亮,原来可以这么玩。
我这里取名为 abc 是为了说明, JSONP 的使用不是说一定要写成 xx/xx/xx?callback=xxx 的格式的,如果你和后台同学约定好了函数名字,你甚至可以不用传callback,直接写成 xx/xx/xx 的接口请求就行了,功能是一定能实现的,只是可能你会被同事打而已。并且, handler 方法里也不一定要传 JSON 格式的内容,你也可以写成 `handler(this)` ,然后前端页面里拿到的就是 handler 函数执行上下文里的 this 变量了,同样,这样写没有任何意义,只会被打而已。也可以写成 `handler('name="服务端给的name"&age="服务端给的age"')` ,这样,通过 & 和 = 去切割获取内容,这样也很麻烦呀,所以最终大家都选择传 JSON 格式的内容,这是最方便获取内容的方式。所以就叫 JSONP 。(这样看来,是不是也可以叫 callbackP 、 STRINGP 呢??)
后语
JSONP 这种技巧,现在(2020-06-01)已经很少有听到有还在使用的。因为现代浏览器基本都支持了 CORS 标准,这可比只支持 GET 的 JSONP 强太多了。以后,笔者估计自己是不会用到 JSONP 了,这篇文章只是笔者看到有些公司在面试时,还是会问 JSONP 的内容。所以就记录一下。
版权声明: 本文为 InfoQ 作者【卡尔】的原创文章。
原文链接:【http://xie.infoq.cn/article/631e3bbb5d5372288509d6dc6】。文章转载请联系作者。
评论