杂谈-JSONP探索

前言

平时工做当中,也已经好久没有用JSONP 来跨域请求了,现从新整理一下,写出本身对 JSONP 的理解。若是写的有不对的,请各位看官评论指出,感谢。

行文时,系统环境为 macOS Mojave v10.14.5,开发工具为 vscode 1.45.1,浏览器为 Goolge Chrome 版本 81.0.4044.138 。 javascript

JSONP是什么

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。html

这是引用了百度百科对 JSONP 的定义。笔者本身的理解是, JSONP 是一种利用浏览器 script 标签的能力实现访问跨域数据的小技巧。就是利用 script 标签能访问跨域资源的能力,利用 JSON 去填充返回内容,以达到跨域的目的。 前端

JSONP解决了什么问题

上文说到了,JSONP 解决了跨域问题。那啥是跨域呢,简单说就是发起请求的网站与被请求的网站,它俩的协议、主机、端口不是彻底同样的。表现就是,跨域时,请求是不会成功的。
JSONP 究竟是怎么实现的呢,笔者的理解是,基于下面三点实现的:java

  1. 浏览器的 script 标签不受同源策略的限制,能够请求到其它源的资源。
  2. script 标签请求的资源拿到后,会被浏览器的 JS引擎 执行。
  3. script 请求到的资源是在 全局上下文 里执行的。

JSONP测试

接下来就写点代码测试一下,并用大白话把过程描述一下。
用koa模拟服务端,代码以下面试

const koa = require("koa");
const mount = require("koa-mount");
const app = new koa();
app.use(
  mount("/jsonp", (ctx) => {
    let callback = ctx.query.abc;
    let javascriptFileText = ` console.log(1); ${callback}("这是服务端的内容"); `;
    ctx.body = javascriptFileText;
  })
);
app.listen(8123);

复制代码

前端代码以下json

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>client</title>
</head>
<body>
    <script> function handler(res) { console.log(res) } window.addEventListener('load', () => { var url = 'http://127.0.0.1:8123/jsonp?abc=handler' var script = document.createElement('script'); script.src = url // 把script标签塞入到文档里,就会发起请求 document.getElementsByTagName('head')[0].appendChild(script); }) </script>
</body>
</html>
复制代码

笔者认为的过程以下:跨域

  1. 服务端接收到 /jsonp这个路由的请求时(固然了,是get请求),就返回一段文本,内容是一个 console.log(1) 和一个函数调用,在这个调用里传入 "这是服务端的内容" 。对于服务端来讲,这一段始终是字符串文本。
  2. _前端在把 script标签塞入到文档后,这个 script 就开始请求,请求拿到后是 console.log(1);handler("这是服务端的内容") 这样的内容,而后浏览器 JS引擎 就把这段内容执行,能够对应 eval() 理解。执行的时候,是处于 全局上下文 的。因此是能拿到 handler 这个函数的。而后呢,在 handler 里就经过res拿到了服务端传回给前端的内容。是否是很妙?!!我第一次用的时候,真的是眼前一亮,原来能够这么玩。
  3. 我这里取名为 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 的内容。因此就记录一下。浏览器

相关文章
相关标签/搜索