想知道jsonp到底是怎么实现的?看我,包教会!

3次阅读

共计 3501 个字符,预计需要花费 9 分钟才能阅读完成。

不管你好不好,反正我是番茄酱。为啥要写这篇文章呢,因为我想写。

看这个文章的你肯定是想学会 jsonp 吧(废话),那遇到这个文章是你的福气。我敢保证这是全网最容易看懂的文章。当然,你如果不会写 js,不懂什么叫跨域,那就算了。别勉强了,勉强是没有幸福的(而且你也没有学习 jsonp 实现方法的必要)。

首先声明,这篇文章不涉及后台代码的具体实现,关于后台的部分只说思路。
好啦,那我们开课啦!
总的实现思路
我这篇教程的结构是总 - 分 - 总(瞎扯的,实际上是总 - 随意 - 随意 -…- 随意)。我们先来说说总的实现思路。
我们都知道由于“同源策略”(不懂啥是同源策略没关系,反正你知道有跨域现象就行了),而导致我们跨域的 ajax 请求发送失败,浏览器报错。
但是呢 script 标签的 src 是没有跨域一说的,也就是说你可以随便引用别的网站的 js。这就是总的实现思路。如果不理解这一点,也不用往下看了,因为你以你的知识储备和理解能力不合适看这文章。

说完总的实现思路,我们来看具体怎么做吧。
1:先忘记我们要实现 jsonp
先忘了我们的目标,看一下我们需要完成 jsonp 而需要掌握的知识。先理解了这些,才能理解 jsonp 的实现。
1.1:基础的 js 代码
我们在页面写个这样的代码:
<script>
function a() {
console.log(‘hello cat!’);
}
</script>
<script>
a();
</script>
运行结果:

对于代码和结果没有异议吧。为啥我要写这样的函数。我要说明的是这样一点:后一个 script 标签里的代码可以引用前一个 script 代码里的函数 (全局)。老规矩,理解了这点就继续往下看。
1.2:script 标签引用文本
我们在 html 里写这样的代码:
<script>
function a() {
console.log(‘hello cat2!’);
}
</script>
然后我们在同路径下新建一个 a.txt。并且 a.txt 里的文本如下:
a();
然后我们在 html 里引用 a.txt。完整的代码如下:
<script>
function a() {
console.log(‘hello cat2!’);
}
</script>
<script src=”a.txt”></script>
刷新页面,控制台如下:

也就是说 txt 里的代码被执行了。所以 a 函数才会被执行。我要说明的是:scritpt 标签引用的外部文件中的文本内容会被当成 js 来解析。
也就是说相当于是这样的代码:
<script>
function a() {
console.log(‘hello cat2!’);
}
</script>
<script>
a();
</script>
1.3:后台返回文本
如果我们的后台给我们返回的不是数据,而是跟 a.txt 一样的文本如下文本:
a();
如我们请求地址为:https://www.a.com/a。则我们此时的完整代码为:
<script>
function a() {
console.log(‘hello cat2!’);
}
</script>
<script src=”https://www.a.com/a”></script>
那可以预见,最终的结果会与 1.2 一致。因为也等于是如下的代码:
<script>
function a() {
console.log(‘hello cat2!’);
}
</script>
<script>
a();
</script>
小结
以上的东西只是需要完成 jsonp 要懂的知识。你理解了可以继续往下看。先不要深究“这样怎么能实现”的问题。不要急,我后面会说的。如果不理解上面的知识可以多看几遍。能够自己动手实验最好。

2:再看看一般的 ajax 请求
我们一般的 ajax 请求,是后台给我们一个请求地址,我们发送请求,然后后台返回给我们 json 格式的信息。例如我们要请求的地址是:
https://www.a.com/userInfo (获取用户信息)
后台应该返回给我们的数据是:
{
“name”: “ 番茄酱 ”,
“wechat”: “fan_qie_jiang666”,
“qq”: “1164431166”,
“email”: “1164431166@qq.com”
}

也就是说我们最终需要的是服务器把 json 格式的数据给我们。但是我们用 1 里说的方法,虽然服务器能调用我们本地的函数,但是我们怎么能获取到数据呢?
那这样,我们把 1.3 的 html 代码改成这样:
<script>
function a(res) {
console.log(res);
}
</script>
<script src=”https://www.a.com/userInfo”></script>

服务器返回的文本改成这样:
a({
“name”: “ 番茄酱 ”,
“wechat”: “fan_qie_jiang666”,
“qq”: “1164431166”,
“email”: “1164431166@qq.com”
});

也就是相当于这样的代码:
<script>
function a(res) {
console.log(res);
}
</script>
<script>
a({
“name”: “ 番茄酱 ”,
“wechat”: “fan_qie_jiang666”,
“qq”: “1164431166”,
“email”: “1164431166@qq.com”
});
</script>

最终结果:

也就是说我们获取到了我们需要的数据。但是万一我们的 function 不叫 a,或者原本叫 a,但是因为种种原因需要改名,这样后台也要跟着改代码。这增加了沟通成本,也增加了后台的工作量。并且可能每个接口你们都需要去沟通这个函数的名字。这是问题呀!

3. 解决函数名的问题
用 script 标签里的 src 相当于向服务器发送了 get 请求。
不管你理不理解上面这点,记住就行了。既然是相当于 get 请求,那就可以带参。并且后台也能获得这个参数的值。
既然这样那我们是不是跟后台沟通好我们给所有用 jsonp 的请求弄个参数,这个参数的值是我们本地的函数名。后台直接给我们返回函数名然后参数为数据值就 ok 辣?不理解的话看下面的过程。
比如我们和后台沟通好参数名叫 balabala,那代码就像下面这样:
<script>
function xiaoMoXian(res) {
console.log(res);
}
</script>
<script src=”https://www.a.com/userInfo?balabala=xiaoMoXian”></script>

后台收到了这个请求,不再像之前那样直接返回给我们 a(…)。
因为我们已经说好了,函数名不再是固定的 a,而是 balabala 这个参数的值才是我们的函数名。
于是后台去获取 balabala 这个参数的值,获取到的是 xiaoMoXian。于是后台返回给我们:
xiaoMoXian({
“name”: “ 番茄酱 ”,
“wechat”: “fan_qie_jiang666”,
“qq”: “1164431166”,
“email”: “1164431166@qq.com”
});

于是代码就相当于是:
<script>
function xiaoMoXian(res) {
console.log(res);
}
</script>
<script>
xiaoMoXian({
“name”: “ 番茄酱 ”,
“wechat”: “fan_qie_jiang666”,
“qq”: “1164431166”,
“email”: “1164431166@qq.com”
});
</script>

最终结果与 2 相同。
小结
以上就是 jsonp 的实现过程。我们已经完成了不用 ajax 来请求,而利用 script 标签 src 属性的跨域特性,来实现我们获取数据的目的。

我来小结下我们用到的知识点:

ajax 请求受同源策略的影响不能跨域。(问题)
script 标签的 src 是可以跨域的,不受同源策略的影响。(总的方法)
后一个 script 标签里的代码可以引用前一个 script 代码里的函数。
scritpt 标签引用的外部文件中的文本内容会被当成 js 来解析。(结合 3 可以获取数据)
用 script 标签里的 src 相当于向服务器发送了 get 请求。(解决函数名的问题)

看到这并且看懂就说明你已经差不多可以毕业了。因为你已经完全懂了 jsonp 怎么实现的。可是我们一般用 jsonp 好像没这么麻烦呀,也不用专门去写个函数来给后台调用,也不用去写 script 标签写 src 到我们的请求地址,也不用沟通什么参数名。哪像你说的这么麻烦!?

哈哈,我要加班啦。预知后事如何,请多点赞。赞够多我就更。

或者加我微信给我发 1 块钱红包,众筹到 10 元我就更(谁还没个身价了~へ~)。

正文完
 0