JSONP

image.png

JSONP:JSON with Padding (跨域获取JSON数据的一种非官方的使用方式)

JSON和JSONP不是一个类型
JSON是数据交换格式
JSONP是一种跨域获取JSON数据的技术
JSONP抓取的资源并不直接是JSON数据,而是带有JSON数据参数的函数执行

客户端期望的返回的:{“name”:”Jacky”,”age”:”18”}

JSONP实际返回的:callback({“name”:”Jacky”,”age”:”18”})

返回不是json类型的数据也可以,img,xml,数组等其它类型数据都可以

jsonp抓取资源不是json数据,是带有json数据或者带有资源参数的一个函数执行,
把数据放在一个函数参数中

在json的基础上做了一个扩展padding,jsonp(adding)

同源策略给谁走了后门

谁可以不受退同源策略的影响,如果同源策略不可以解决,那会非常麻烦

同源策略在浏览器端给一些资源开了后门

  1. img的src引入不同源的图片资源
    2. link的href引入不同源的样式资源
    3. iframe的src引入不同源的网页资源
    4. script的src引入不同源的脚本文件资源

总结

带src的,带href属性的标签,不受同源策略影响

图片

  1. <img src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="">

image.png
image.png
右键复制图像链接,给src标签赋值
http://localhost:63342/与src的链接
https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png
并不同源,但却可以得到图片资源,说明是跨过了同源的限制

cdn搜索

https://fontawesome.dashgame.com/
image.png
搜索font awesome cdn

引入css

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <!--<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">-->
  8. <body>
  9. <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  10. <img src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="">
  11. <i class="fa fa-angle-double-down"></i>
  12. </body>
  13. </html>

image.png
image.png
在scources可以看到是否引入资源成功

iframe、script引入资源

index.html

  1. <script src="./js/index.js"></script>
  2. <!--引入index代码,相当于如下代码,相当于新开一个script,并把index.js中的代码重写一遍-->
  3. <!--<script>
  4. var a = 1;
  5. </script>-->
  6. <script !src="">
  7. console.log(a);
  8. </script>

运行网页html,结果如下
image.png
打印a的结果1

index.js

  1. var a=1;

引入index代码,相当于如下代码,相当于新开一个script,并把index.js中的代码重写一遍

相当于

  1. <script>
  2. var a = 1;
  3. </script>
  4. <script !src="">
  5. console.log(a);
  6. </script>

把index.js后缀名改成txt,再引入照样可以运行,打印1

  1. <script src="js/index.txt"></script>
  2. <script !src="">
  3. console.log(a);
  4. </script>

txt现象理解

无论后缀名是什么,只在乎里面内容是什么,与后缀名无关,因为script标签本身就是引入脚本的,script会只看里面的内容,因为script本身就是引入脚本的

因为script标签本身就是拿来解析脚本或者写脚本用的,文件后缀名对于script标签来说本身根本不重要,因为引入进来的东西,会把它当做脚本,只要一引入进来首先会看里面的内容,看里面的内容是不是符合脚本,是不是符合js脚本,是不是符合ecma规范,预编译,只要内容符合脚本就正常解析,如果里面有错误,再报错。如果不符合ecma规范就报错

后缀名对于script来说就没有用处,有些大厂js文件,后面没有后缀名

不是script会优先把文件当做js代码来解析,不能这么理解,也不能说没有道理

如果一个文件没有后缀,那么window会当成是txt文件

html

  1. <script !src="">
  2. function test(str){
  3. console.log(str);
  4. }
  5. </script>
  6. <script src="./js/index.js"></script>

index.js

  1. test("js++")

可以运行,结果
image.png
在html写代码定义,在js写执行,也可以运行

  1. <script src="./js/index.js"></script>
  2. <script !src="">
  3. function test(str){
  4. console.log(str);
  5. }
  6. </script>

image.png

  1. <script !src="">
  2. function test(str){
  3. console.log(str);
  4. }
  5. </script>
  6. <script src="./js/index.js"></script>
  7. <script src="./server/index.php"></script>
  1. <?php
  2. echo 'test("js++")';

phpsyudy 通过www运行才可以成功,用服务器解析php代码,解析成js代码,浏览器端解析不了php代码

image.png

  1. <?php
  2. $data
  3. echo 'test($data)';

如果把从数据库中取出来的$data数据,通过test方法加参数传过来,可以通过script标签接收到,test($data),方法+参数

jsonp

  1. <script src="http://test:jsplusplus.com/jsonp/jsonp.js"></script>
  2. <script !src="">
  3. console.log(a)
  4. </script>

jsonp.js

  1. var a=1;

打印a=1

jsonp.js

  1. var a = 1;
  2. function getParams() {
  3. var path = document.getElementById('jsonpScript').src,
  4. callback = path.match(/cb=(.*)/)[1];
  5. switch (callback) {
  6. case 'test1':
  7. test1('test1');
  8. break;
  9. case 'test2':
  10. test2('test2');
  11. break;
  12. case 'test3':
  13. test3('test3');
  14. break;
  15. default:
  16. test1('test1');
  17. }
  18. }
  19. getParams();

index.html

  1. <script !src="">
  2. function test1(str){
  3. console.log(str);
  4. }
  5. function test2(str) {
  6. console.log(str);
  7. }
  8. function test3(str) {
  9. console.log(str);
  10. }
  11. </script>
  12. <script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test3" id="jsonpScript"></script>
  13. <script !src="">
  14. console.log(a)
  15. </script>

通过改变改变cb=test1|test2|test3,改变方法
image.png

jsonp是一个无比简单的东西,之所以有人学不会,是因为基础没有弄明白,最基础的没有弄好

index.html引用外界脚本script

分析

写了三个函数,通过cb把函数名称给服务器上的js代码,js代码通过运行,通过id得到元素,可以得到元素的src属性,得到字符串http://test:jsplusplus.com/jsonp/jsonp.js?cb=test3,通过正则表达式,提取出来test3,通过switch判断,运行代码,通过get传值把数据传给页面

jsonp

  1. test({"name":"Jacky","age":"35","sex":"male"});
  1. <script !src="">
  2. function test(str){
  3. console.log(str);
  4. }
  5. </script>
  6. <script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test" id="jsonpScript"></script>
  7. <script !src="">
  8. console.log(a)
  9. </script>

image.png

jsonp.js

  1. $.ajax({
  2. url: 'http://test.jsplusplus.com/get_courses.php',
  3. type : 'post',
  4. data : {
  5. status:1
  6. },
  7. success : function(data){
  8. test(data);
  9. }
  10. })
  1. <script !src="">
  2. function test(data){
  3. console.log(data);
  4. }
  5. </script>
  6. <script src="http://test:jsplusplus.com/jsonp/jsonp.js" ></script>

image.png

index通过src引入jsonp.js代码,jsonp发起ajax请求,把ajax请求的数据通过index中的方法,把参数传过去

这就相当于

  1. <script !src="">
  2. function test(str) {
  3. console.log(str);
  4. }
  5. </script>
  6. <script !src="">
  7. test('我是test源下的jsonp.js');
  8. </script>
  9. <script src="http://test:jsplusplus.com/jsonp/jsonp.js?cb=test"></script>

jsonp.js
引入脚本,相当于新建脚本,把代码复制粘贴到引入的地方,等价替换

  1. test('我是test源下的jsonp.js');
  1. <script !src="">
  2. function test(data) {
  3. console.log(data);
  4. }
  5. </script>
  6. <script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test"></script>

image.png

image.png
不管脚本是前端的还是后端,只要返回的是test(‘js++’),就可以解析,后缀名是js、php都可以,只关心最终返回的东西,如果不符合ecma的规范,会报错

jsonp都是后端写好的,与后端商量好,前端要接口
cb、callback商量好

封装

  1. <script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test1"></script>
  2. <script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test2"></script>
  3. <script src="http://test:jsplusplus.com/jsonp/jsonp.php?cb=test3"></script>

请求多个资源,需要多个script引入不同的接口,需要写很多script,这样做不太合理

  1. <button id="btn">获取资源</button>
  2. <script !src="">
  3. var oBtn=document.getElementById('btn');
  4. oBtn.onclick=function (){
  5. oSCript=document.createElement('script');
  6. oSCript.src='http://test.jsplusplus.com/jsonp/jsonp.php?cb=test';
  7. document.body.appendChild(oSCript);
  8. document.body.appendChild(oSCript);
  9. }
  10. function test(data){
  11. console.log(data)
  12. }
  13. </script>

不用写延迟,因为js执行时,是一行一行执行的
cb=test得与function test一致就行

动态创建,script标签

image.png

image.png
百度搜索就是用jsonp获取资源的

image.png
百度是个跨域请求sp0.baidu.com

jquery封装的jsonp获取

image.png
把jsonpCallback注释掉
image.png
就有这个乱码了

百度就是用的jquery的ajax封装的jsonp获取,没有自己封装

封装的ajax中添加jsonp的封装

在封装的ajax中添加,以下代码

  1. jsonp = opt.jsonp || 'cb',
  2. jsonpCallback = opt.jsonpCallback || 'jQuery' + randomNum() + '_' + new Date().getTime();
  3. if(dataType.toUpperCase() === 'JSONP' && method !== 'GET') {
  4. throw new Error('如果dataType为JSONP,请您将type设置成GET');
  5. }
  6. if(dataType.toUpperCase() === 'JSONP') {
  7. var oScript = document.createElement('script');
  8. // xxx.domain.com/xxx.php?cb=test
  9. // xxx.domain.com/xxx.php?wd=xxx&cb=test
  10. oScript.src = url.indexOf('?') === -1
  11. ? url + '?' + jsonp + '=' + jsonpCallback
  12. : url + '&' + jsonp + '=' + jsonpCallback;
  13. document.body.appendChild(oScript);
  14. document.body.removeChild(oScript);
  15. window[jsonpCallback] = function(data){
  16. success(data);
  17. }
  18. }
  19. //随机数,上面的随机数
  20. function randomNum(){
  21. var str = '';
  22. for(var i = 0; i < 20; i++) {
  23. str += Math.floor( Math.random() * 10);
  24. }
  25. return str;
  26. }

总结

jsonp只有get请求才行,post不行,因为后面没有参数

利用src是没有限制的,,在src中写后端脚本,让后端脚本拼接出来,要的前端的脚本,也就是函数执行,拼接好,返回响应给客户端,data作为函数的参数,传过来

image.png
image.png

image.png

image.png
拼接字符串

百度联想词

浏览器操作

清空没有信息
image.png

点击红色按钮停止记录网络日志,再点开记录网络日志,清零网络日志
image.png

image.png

image.png

现在的百度响应
image.png
基本上输入一个字母就请求一次,上下两个差了一个n

image.png

之前的百度响应,与现在的不一样
image.png

复制请求url,到浏览器地址栏
image.png

复制请求url,到浏览器地址栏,跳转,结果显示一段文本,这是fehelper解析后的
image.png

g联想词

不解析应该是这样的格式
image.png

搜索京东,url有很长的后缀,把后缀都给删除了,照样可以跳转
image.png

image.png

项目