跨域解决方法——jsonp原理

  • 一个域名地址的组成:
    在这里插入图片描述
  • 当协议、子域名、主域名、端口号任意一个不相同时,都算作不同域,不同域之间相互请求资源,就算做“跨域”。由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题。
  • 使用jquery的jsonp可以发起跨域请求,下面来探究下他的原理及使用。

首先看下如何使用<script src="">来完成一个跨域请求:

普通的ajax请求是会发生跨域问题的,但是img的src,a的href,script的src却可以发起任意网址的请求并接收到响应,于是我们首先利用script的src来完成一个跨域请求。
客户端:

<script>
    function show(weather){
        document.write(weather)
    }
    //show('返回的数据');
</script>
<!--用请求参数将函数名传递给服务器。-->
<script src="http://localhost:3000?callback=show"></script>

服务器端:

const http = require("http");
const url = require("url");
http.createServer(
    (req,res)=>{
        var Url = url.parse(req.url,true);
        //接收客户端传过来的名为callback的参数中保存的函数名
        var callback = Url.query.callback;
        var weather="北京 晴";
        //将函数名动态拼接到要返回的函数调用语句中。
        res.write(`${callback}("${weather}")`);//实际想要在客户端执行的函数调用语句。
        res.end();
    }
).listen(3000);

script只能识别js语句,一旦接收到js语句就立即执行。于是在服务器端拼接一条函数调用的js语句,并且提前在客户端定义一个函数,当客户端接收到服务器返回的js语句后就会立即执行。
为了使函数名在客户端可修改,于是用请求参数将函数名从客户端传递给服务器。

动态创建script元素

script是在页面中写死的,只能在页面加载过程中执行一次,如果想每次单击按钮,随时发送请求,可以每次单击按钮时动态创建script元素。

<body>
<button>发送请求</button>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
    function show(weather){
        alert(weather);
        $("body>script:last").remove();//删除创建的那个script元素
    }
    //show('返回的数据');
    $("button").click(function(){
        var script = document.createElement('script');
        script.src="http://localhost:3000?callback=show";
        document.body.appendChild(script);
    })
</script>
</body>

jQuery对jsonp方式跨域进行了终极简化

1.服务端代码不变,js代码如下:
最简单的方式,只需配置一个dataType:‘jsonp’,就可以发起一个跨域请求。
jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。//callback: jQuery34105977893922582984_1578207815633
_: 1578207815634
这里的success就跟上面的show一样,如果有success函数则默认success()作为回调函数。

<body>
<button>发送请求</button>
<script src="jquery.js"></script>
<script>
    $("button").click(function(){
        $.ajax({
            url: "http://localhost:3000",
            type: "GET",
            dataType: "jsonp",  //其实也是动态创建script,借助script发送跨域请求,必须有服务端的支持,
            success: function(weather) {
                alert(weather);
            }
        })
    })
</script>
</body>

2.再看下如何指定特定的回调函数:
jsonpCallback: “show”,
看请求参数 callback: show_: 1578208620937,请求时带的参数是:callback=show;调用回调函数的时候,先调用了指定的show,然后再调用了success。所以,success是返回成功后必定会调用的函数,就看你怎么写了。

<script>
    function show(weather) {
        alert("show"+weather);
    }
    $("button").click(function(){
        $.ajax({
            url: "http://localhost:3000",
            type: "GET",
            dataType: "jsonp", 
            jsonpCallback: "show",   //指定特定的回调函数
            success: function(weather) {
                alert(weather);
            }
        })
    })

</script>

3.再看看如何改变callback这个名称:
jsonp: “func”,
看请求信息:func: show_: 1578208954673

<script>
    function show(weather) {
        alert("show"+weather);
    }
    $("button").click(function(){
        $.ajax({
            url: "http://localhost:3000",
            type: "GET",
            dataType: "jsonp",
            jsonp: "func",               //改变callback这个名称
            jsonpCallback: "show",
            success: function(weather) {
                alert(weather);
            }
        })
    })

</script>

指定callback这个名称后,后台也需要跟着更改。

http.createServer(
    //每当有客户端发来请求时,自动调用一下回调函数。
    (req,res)=>{
        var Url = url.parse(req.url,true);
        //接收客户端传过来的名为callback的参数中保存的函数名
        var callback = Url.query.func;
        var weather="北京 晴";
        //将函数名动态拼接到要返回的函数调用语句中。
        res.write(`${callback}("${weather}")`);//实际想要在客户端执行的函数调用语句。
        res.end();
    }
).listen(3000);
总结

jsonp的实现方式其实也是动态创建script,借助script发送跨域请求,jquery中ajax的jsonp对这个复杂的过程进行了封装,并且需要服务端的支持,所以可想而知,jsonp是不支持POST方式的。

jsonp的原理:
动态创建script标签,并且自动给script的src属性加入了callback参数,借助script来发送跨域请求,请求结束后script会被自动删除。并且必须有服务器端配合接收callback保存的函数名,服务端将要返回的数据填充到函数调用语句里返回,客户端收到js语句执行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值