JSONP的原理

基本原理

基本原理: 主要就是利用了 script 标签的src没有跨域限制来完成的。

详解: 利用script标签不受同源策略的影响,通过src属性向后端发送请求,后端接受到请求之后,根据前端请求地址中的callback回调函数的名字 来把JSON数据填充到回调函数内部, 进行返回. 前端在接收到返回结果之后 自动的调用本地callback中填写的方法 实现数据获取

执行过程

执行过程:

  • 前端定义一个解析函数(如: function hello (data) {})
  • 通过params的形式包装script标签的请求参数,并且声明执行函数(如callback=hello )
  • 后端获取到前端声明的执行函数( hello ),并以带上参数且调用执行函数的方式传递给前端
  • 前端在script标签返回资源的时候就会去执行 hello 并通过回调函数的方式拿到数据了。

优缺点

缺点:

  • 只能进行GET请求

优点:

  • 兼容性好,在一些古老的浏览器中都可以运行

案例分析

先来看看我们要实现一个什么效果:

前端简单实现

在一个叫index.html的文件中有以下代码:

script type='text/javascript'>
     function hello(data) {
        console.log(data)
    }
</script>
<script src='http://localhost:8080/api/jsonp?id=1&callback=hello' type='text/javascript'></script>

这两个script的意思是:

  • 第一个,创建一个hello函数。但是它还没有被调用
  • 第二个,加载src中的资源,并等待请求的内容返回

模拟后端代码

const http = require("http"); //网络请求模块
const urlModel = require("url"); //解析URL地址模块
const fs = require("fs"); //文件操作模块
//创建一个httpServer
let serve = http.createServer();
//监听"request"事件, 设置监听回调
    // req -> request请求
    // res -> response响应
serve.on("request", function (request, response) {
	// 模拟数据
    let a = {  
        a: 100,
        b: 200
    };
    //用urlModel.pares把请求url转换成对象形式 
    let callbackObj = urlModel.parse(request.url, true).query;
  
    //返回数据字符串,把真正数据转换成字符串拼接为函数调用
    response.write(callbackObj.callback + "(" + JSON.stringify(a) + ")");
    //发送响应
    response.end();
});
serve.listen(8080, function () {
    console.log("服务器运行在8080端口")
});

整个过程就是:

  1. 当执行到第二个script的时候,由于请求了我们的8080端口,并且 callback 这个参数放到URL里。那么后台就可以拿到URL里的这个参数。
  2. 也就是在后端代码中的 callbackObj = urlModel.parse(request.url, true).query 这里获取到了这个对象 { callback : hello }
  3. 在这个对象里可以拿到我们传过来的 hello 函数 ,这里也就是告诉后端,前端那里是会有一个叫做hello 的函数来接收后端想要返回的数据,而后端你只需要在返回体中写入hello ()就可以了。
  4. 前端在得到了后端返回的内容 callback ,发现里面是一段执行函数的语句,因此就会去执行第一个script中的 hello() 方法了,并且又是带了参数的,所以此时浏览器控制台会打印出{ a: 100 ,b : 200 }

以此来达到一个简单的跨域的效果。

下面给大家推荐一个写的比较好的JSONP简书,本人也有借鉴

链接:https://www.jianshu.com/p/88bb82718517

上一篇:JSONP


下一篇:前后端跨域问题解决