如何通过JSONP实现跨域,原生的js实现jsonp的跨域封装

该种跨域的央求格局亟待后台同盟再次来到响应的函数推行多少

后台jsonp.php的代码:

为啥会有跨域难题? - 因为有同源计策

  1. 同源攻略是浏览器的生机勃勃种安全战略,所谓同源指的是 央求U汉兰达L地址中的 协议, 域名端口 都相同,如若当中之一不平等尽管跨域

  2. 同源战术主要为了保险浏览器的安全性

  3. 在同源策略下,浏览器 不准 Ajax跨域获取服务器数据

    http://www.example.com/detail.html
    跨域请求:
        http://api.example.com/detail.html 域名不同
        http://www.example.com:8080/detail.html 端口不同
        http://api.example.com:8080/detail.html 域名、端口不同
        https://api.example.com/detail.html  协议、域名不同
        https://www.example.com:8080/detail.html 端口、协议不同
function jsonp (url, data, callback) { let scriptTag = document.createElement('script') let params = '' for (key in data) { params += key + '=' + data[key] + '' } params.length === 0 ? scriptTag.src = url + '?' + 'fn=' + callback : scriptTag.src = url + '?' + params + 'fn=' +callback document.querySelector('head').appendChild(scriptTag)}function myCallback(){ alert('success')} jsonp ('123', {name:'lhy'}, 'myCallback')

解决方法 JSONP 的规律解析

JSONP的规律:利用 script标签 的 src属性 进行跨域央求,服务器响应函数调用传参

那边掌握 JSONP的法则 并扩充测量检验,内需不一样域,笔者这边是 apache 服务器,本身配置了 四个虚构主机 做的。

两个域 代码所在域 , 请求域


二、封装代码

提出:onload、onreadystatechange 写在src赋值早前,防止载入js太快而从未给onload、onreadystatechange 赋值(Image对象在IE下有所此类现象)。

大约包装

地点正是 JSONP 的大器晚成体法则了,上边是 学习中完毕的 jquery ajax JSONP 格局的 粗略包装,感兴趣的能够参谋一下。

    function ajax( obj ){
        // 默认参数 由于 jsonp 原理是 在 url体 中传递,
        // 所以仅支持 get, 所以不对 type 进行配置
        var defaults = {
            url : '#',
            dataType : 'jsonp',
            jsonp : 'callback',
            data : {},
            success : function( data ) { console.log( data ) }
        }

        // 处理形参,传递函数的时候就覆盖默认参数,不传递就使用默认的参数
        for ( var key in obj ) {
            defaults[ key ] = obj[ key ];
        }

        // 这里是默认的回调函数名称,根据当前日期和随机数生成
        var cbName = 'jQuery' + ('1.11.1' + Math.random()).replace(/D/g,"") + '_' + (new Date().getTime());// 去掉所有的小点,相当于 jquery 后面加一串数字_再加上时间数字
        if( defaults.jsonpCallback ){
            cbName = defaults.jsonpCallback;
        }

        // 这里就是回调函数,调用方式:服务器响应内容来调用
        // 向window对象中添加了一个方法,方法名称是变量cbName的值
        window[ cbName ] = function( data ){
            defaults.success( data );//这里success的data是实参
        }

        // 将所传参数 data 进行处理,添加到 src url中
        var param = '';
        for( var attr in defaults.data ){
            param += attr + '=' + defaults.data[ attr ] + '&';
        }
        if( param ){  // 去掉最后的一个 &
            param = param.substring( 0, param.length-1 );
            param = '&' + param;
        }

        // 动态添加 script 标签, 配置参数
        var script = document.createElement( 'script' );
        // defaults.jsonp 后台 get 变量名,cbName 回调函数名, param 变量
        script.src = defaults.url + '?' + defaults.jsonp + '=' + cbName + param; 
        var head = document.getElementsByTagName( 'head' )[ 0 ];
        head.appendChild( script );
    }

jsonp是行使浏览器乞求script文件时不受同源战略的约束而贯彻的,杜撰叁个script标签,将呼吁数据的url赋值给script的src属性,并将该标签增加到html中,浏览器会活动发送央求,重临的相符时大器晚成段js代码,即函数的调用代码。

不问可以看到解释:我们经过创办script,然后钦点它的src等品质,然后插入到head试行。

驱除Ajax 跨域难点 - JSONP原理分析

时间: 2018-12-22阅读: 443标签: jsonp一、原理

通过yui的get.script(卡塔尔(قطر‎去触发url,代替了原本的script标签。将回来的数码填充到页面来显示。

JSONP基本原理 - 静态方法创立

笔者们透过上面静态方法创造的测量检验来看看JSONP化解跨域难题的基本原理

  • 测试1:

    目的伏乞地址,http:/www.jepson.com/1.php

        <?php
            echo "1;";
         ?>
    

    在 peter.com/1.html 内部,通过 script标签进行呼吁

      <script type="text/javascript" src="http://www.jepson.com/1.php"></script>
    

打开F12,进入 network,找到 1.php的不行央求,选中 Response,开掘结果是 1,跨域诉求就那样成功了! 没有错原理正是那样轻松。

不过有未有开采,我们是回天乏术获取这么些央求到的数码的,如何做?

script标签私下认可是同步加载的,那大家就 echo ‘var a = 1;’ ,获取过来正是‘var a = 1;’, 那是还是不是就是足以感觉评释了三个变量并赋值了?

又因为是一同的,所今后边的 script语句是否就能够用这一个 a 了?大家来试后生可畏试

  • 测试2:

    目的供给地址,http:/www.jepson.com/2.php,就大器晚成行

      <?php
          echo "var a = 1;";
       ?>
    

在 peter.com/2.html 中间,通过 script标签进行倡议

    <!--  我是不是可以理解为这里声明了一个变量? var a = 1; -->
    <script type="text/javascript" src="http://www.jepson.com/2.php"></script>
    <script type="text/javascript">
        console.log( a );   // 1
    </script>

F12 张开调整台,没错!你输出 a 了, 输出的值为 1,大家得到了后台传输的数量

不过,这种静态的不二等秘书诀分明有好些个破绽,首先要放在代码的顶端,不然上边包车型客车没有办法用到重临的数据

其次,这种静态的点子传参配置十分不实惠,于是乎大家日常选用 动态成立script标签的艺术,增多到底部,并配参数


此间须要后台重回的参数名称叫fn

简短利用jsonp的demo:

JSONP基本原理 - 动态方法创制

动态创造script标签的不二等秘书诀,加多到尾部,并配参数,能够消除静态创设的弊病。

  • 测试3:

    目的央求地址,http:/www.jepson.com/3.php,就大器晚成行

      <?php
          echo "var a = 1;";
       ?>
    

    在 peter.com/3.html 里头,通过 script语句动态成立 script标签进行倡议

         <script type="text/javascript">
             var script = document.createElement('script');
             script.src = 'http://www.jepson.com/3.php';
             var head = document.getElementsByTagName('head')[0];
             head.appendChild(script);
             console.log( a );
         </script>
    

开垦 F12,令人震憾的业务产生了,** 居然报错了,**Uncaught ReferenceError: a is not defined(…) ?? a变量未有 定义?

咱俩打开 network,找到 1.php这一个央浼,点开response,发现有 ‘var a = 1;’,央浼成功了呀?那是如何动静?

在乎留神:原来动态创造 script 的办法出殡诉求是异步的,尽管央浼成功了,不过在采用变量时,乞请还未完成,也就是还从未概念变量,然后就报错了。

那如何是好?这里有二个小技艺, 大家能够 echo ‘foo( 123 )’; 那样相当于央求完成实践 foo(123),即调用我们代码中foo函数,大家在代码中写二个函数 function foo( data 卡塔尔国 { console.log( data 卡塔尔国; } 那就也便是举行了回调,大家得到了数量。上边是代码演示。

  • 测试4:

    对象伏乞地址,http:/www.jepson.com/4.php

        <?php
            echo 'foo(123)';
         ?>
    

    在 peter.com/4.html 中间,通过 script语句动态成立 script标签实行号令

        <script type="text/javascript">
            var script = document.createElement('script');
            script.src = 'http://www.jepson.com/4.php';
            var head = document.getElementsByTagName('head')[0];
            head.appendChild(script);
    
            function foo(data){
                console.log( data );    //foo(123) 对 foo 调用 输出 123
            }
        </script>
    

    F12 能够观察 输出 123 了, 况兼在network中查阅需要,response 能够看到是 foo(123卡塔尔国

    那大家就可以用这种动态的章程 很自在的 得到后台数据了,只不过前台表明的和 后台 调用的 函数名 需要一样才行,如下边包车型客车foo,那样就不太好了,每一遍改动,那都要对接一下。

    进而大家得以把回调函数名放在参数中传输。案譬喻下:

  • 测试5:

    指标须要地址,http:/www.jepson.com/5.php

        <?php
            $cb = $_GET[ 'callback' ];    // get 通过 callback键 得到 函数名
            $arr = array( 'username' => 'zhangsan', 'password' => '123456' );// 我们也可以传复杂一点的数据
            echo $cb.'('. json_encode($arr) .');';// hello( json_encode($arr) )
        ?>
    

    在 peter.com/5.html 里面,通过 script语句动态成立 script标签进行倡议

        <script type="text/javascript">
            function hello(data){
                console.log(data);// Object {username: "zhangsan", password: "123456"}
                console.log(data.username); // zhangsan
                console.log(data.password); // 123456
            }
            var script = document.createElement('script');
            script.src = 'http://jepson.com/5.php?callback=hello';
            var head = document.getElementsByTagName('head')[0];
            head.appendChild(script);
        </script>
    

**总结:**jsonp的真相:动态创制script标签,然后经过它的src属性发送跨域央求,然后服务器端响应的数额格式为【函数调用】,所以在发送央浼此前必须先声美素佳儿个函数,何况函数的名字与参数中传送的名字要后生可畏致。这里证明的函数是由服务器响应的源委(实际便是风流罗曼蒂克段函数调用js代码)来调用。JSONP是一个公约。


<!DOCTYPE HTML>
<html>
<head>
    <meta charset="gbk"/>
    <title></title>
    <script type="text/javascript"
            src="http://ajax.googleapis.com/ajax/libs/yui/2.8.1/build/yuiloader-dom-event/yuiloader-dom-event.js"></script>
</head>
<body>
<div id="console"></div>
<script>
    var url = "http://www.bkjia.com/test.php";
    var AjaxLoader = function() {
        var loader = function() {
            YAHOO.util.Get.script(url + '?callback=AjaxLoader.reload', {
                onSuccess: function() {
                },
                onFailure: function() {
                    YAHOO.util.Dom.get("console").innerHTML = '请求失败';
                },
                timeout: 10000,
                autopurge: true,
                charset: 'GBK'
            });
        };
        return{
            init: function () {
                loader();
                YAHOO.util.Dom.get("console").innerHTML = '开始请求';
            },

            reload:function() {
                YAHOO.util.Dom.get("console").innerHTML = '请求成功,调用成功';
            }
        };
    }();
    AjaxLoader.init();
</script>
</body>
</html>

运用 jquery ajax-JSONP格局调用 化解跨域

纵然如此 jsonp 的贯彻跟 ajax 未有半毛钱关系jsonp是通过 script的src实现的(具体看前面包车型大巴深入分析),可是最后指标都以向服务器恳求数据然后回调,并且为了方便,所以jquery把 jsonp 也封装在了 $.ajax 方法中,调用格局与 ajax 调用方式略有分歧,案比如下。

  • 测试jq_jsonp:

    对象诉求地址,

        <?php
            $cb = $_GET[ 'callback' ];    // 获取回调
            $arr = array( 'username' => 'zhangsan', 'password' => '123456' );
            echo $cb.'('. json_encode($arr) .');'; // 返回回调函数调用
    
            // 就是 jQuery1111011117830135968942_1478857963357({"username":"zhangsan","password":"123456"});
        ?>
    

    在 peter.com/jq_jsonp.html 里面,通过 Jquery ajax 方法, JSONP 方式调用,举行倡议

        <script type="text/javascript" src="./jquery.js"></script>
        <script type="text/javascript">
            $(function(){
                $("#btn").click(function(){
                    $.ajax({
                        type:'get',
                        url:'http://www.jepson.com/jq_jsonp.php',
                        dataType:'jsonp',
                        jsonp: 'callback', // 回调函数,后台get接收的变量名,默认 就callback
                        // jsonpCallback: 'abc',    回调函数名,默认是一长串,jquery自动生成的,在请求url中可以看到
                                                // 改不改无所谓,改短一点也只是 查看请求url的时候清晰一点而已
                        success:function(data){
                            console.log(data.username,data.password);   // zhangsan 123456
                        },
                        error:function(data){
                            console.dir(data);
                            console.log('error');
                        }
                    });
                });
            });
        </script>
        <body>
            <input type="button" value="点击" id="btn">
        </body>
    

    能够看出,输出了 ‘zhangsan 123456’。

    注意:若后台没做获得回调,重临函数调用的做事,那么就可以出错,步入error方法。这是办事中常会遭受的不当,这里要小心


<!DOCTYPE HTML>
<html>
<head>
    <meta charset="gbk"/>
    <title></title>
</head>
<body>
<div id="content">

</div>
</body>
<script type="text/javascript">
    var load = function(message){
        document.getElementById("content").innerHTML=message;
    }
</script>
<script type="text/javascript" src="jsonpContent.html?callback=load"></script>
</html>

日常的ajax央浼只可以进展同域的数目人机联作,然而只要有跨域的景况就十二分了。可是jsonp分化,他得以采取浏览器标签达到跨域的目标。 其实 jsonp 是个很简单的多个东西。主倘诺行使了 <script> 标签对 javascript 文书档案的动态解析。

var JSONP = document.createElement("script") ;
//FF:onload IE:onreadystatechange
JSONP.onload = JSONP.onreadystatechange = function(){
 //onreadystatechange,仅IE
 if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
  alert($("#demo").html());
  JSONP.onload = JSONP.onreadystatechange = null//请内存,防止IE memory leaks
 }
}
JSONP.type = "text/javascript";
JSONP.src = "http://www.bkjia.com/js/jquery.js";
//在head之后添加js文件
document.getElementsByTagName("head")[0].appendChild(JSONP);

咱俩得以率先定义二个函数来奉行JSONP重返的多寡,然后经过JSONP的src传此函数给后台,实行拍卖,重临可举办的函数。举个例子下边代码:

echo $_GET["callback"]."('hello,world')";

对于地点的分解,我们能够归纳那样敞亮:JSONP正是足以经过JavaScript文件举行跨域通信的法子,比如:未来各大网址风靡的研究提醒。注意:JSONP服务器端代码要求丰裕做好安全措施。

下边是二个简约的JSONP:

function jsonpHandle(a){
    alert(a);
}
var JSONP = document.createElement("script") ;
JSONP.type = "text/javascript";
JSONP.src = "http://www.js8.in/jsonp.php?callback=jsonpHandle";
//在head之后添加js文件
document.getElementsByTagName("head")[0].appendChild(JSONP);

那是最主题的jsonp的法则。

with Padding。由于同源攻略的范围,XmlHttpRequest只允许需要当前源(域名、公约、端口)的财富。假诺要实行跨域央求,大家能够通...

Script 标签本身的职能正是异步加载js何况会以js的办法分析推行。意气风发旦在script的标签里参与src的性能,浏览器施行到那些标签时就重临乞请钦命的地点,要是服务器再次来到的是js格式的代码,以致足以是js的函数,只若是能被js深入解析的,都得以被实行,那也正是jsonp的原理。

JSONP即JSON with Padding。由于同源计策的限量,XmlHttpRequest只同意央求当前源(域名、左券、端口)的能源。如果要实行跨域央浼,大家得以经过行使 html的script标志来扩充跨域央求,并在响应中回到要试行的script代码,个中能够一贯使用JSON传递javascript对象。这种跨域的报纸发表情势叫做JSONP。

本文由澳门威斯尼人平台登录发布于Web前端,转载请注明出处:如何通过JSONP实现跨域,原生的js实现jsonp的跨域封装

相关阅读