ajax跨域获取数据解决方案---JSON

来源:互联网 发布:js 添加卡片效果 编辑:程序博客网 时间:2024/06/02 13:32

跨域:跨域名

一个域名下的文件去请求和其不在同一域名下的资源文件时,就会产生跨域请求,这样是不允许的,是安全限制问题。

Ajax跨域操作时,报错:XMLHttpRequest cannot load …… ‘Access-Control-Allow-Origin’header is present on the requested resource.

跨域请求资源的解决方案:

  •  通过Flash 跨域请求资源,在服务器设置一个xml文件(类似于域名菜单), 将当前域名设为请求资源域名的白名
  •   本地代理:通过服务器端中转(代理作用)来请求资源,服务器端资源请求没有跨域的限制,在在当前域名的服务器上新建php文件,请求跨域资源到该服务器上,再从客户端访问当前域名对应服务器上的php资源。   互联网上,一台台服务器是通过不同的IP来进行识别的。每台服务器上可以新建很多站点,您的网站程序就放在一个站点里面然后在这个站点上绑定您的域名。所以一台服务器可以绑定很多个域名,也就是一个IP可以对应很多个域名,但是一个域名只能绑定到一个站点上,也就是对应一个IP
  •  Script 标签

 JSONP :JSON with Padding

概念理解:

  • JSONP是一个非官方的协议,通过Javascript Callback的形式实现跨域访问
  • JSONP通过使用JSON和<script>标签相结合的方法,可以绕过同源策略,从服务器端直接返回可执行的Javascript函数调用或JavaScript对象
  • 将JSON格式的数据,使用内嵌形式,拿来使用
  • JSONP已经成为各大公司的Web应用程序跨域首选,如Youtube GData, Digg, 豆瓣等

原理:Script 标签:

  •  HTML中的script标签可以加载外部资源:<script src = ””></script>
  •   用 script标签加载的资源没有跨域限制。如加载baidu的JQuery资源
  •  以前用到的script标签加载的都是.js文件,其实script标签解析的不是文件后缀名,而是文件中的内容,通过script标签可以加载网址,网址中对应文件的内容是没有变量名的JSON对象,这是问题,加载进来的数据无法引用!!
  •  jsonp的使用方式:内填充

<script src=”1.txt” ></script><script>   function fn(data){     alert(data);   }</script>

        1.txt文件中的内容为:

             fn([1,2,3]);

      即:在资源加载进来之前先定义好一个函数,这个函数接收一个参数(数据),函数体中利用该参数做数据处理。

     然后需要的时候通过script标签加载远程文件资源,当远程文件资源被加载进来的时候,就会执行前面定义的函数,并把数据当作该函数的参数传入。

       function fn(data){  <!-- 声明全局函数fn() -->

             //to do sth }

         <!-- <scriptsrc="1.txt"></script> 点击按钮时,动态创建 -->

    <!-- 1.txt文件调用了上面定义的全局函数fn,因此才能进行访问交互 -->     

window.onload = function() {var  oBtn = document.getElementById('btn');oBtn.onclick = function() { //当按钮点击的时候再去加载远程资源,让他执行             var oScript =document.createElement('script');             oScript.src = '1.txt';            document.body.appendChild(oScript);     }}

  利用jsonp跨域请求资源

    <inputtype="button" id="btn" value="点我"/>

当点击页面上的按钮时,就会弹出1.txt中的数组[1,2,3],用法很像ajax。

这种交互方法存在以下缺点:

当要点击不同的按钮,远程访问不同的资源并在HTML文档不同的地方显示时,类似于下面这种多接口的操作太麻烦了,每次访问新的资源时,都要跟后端交互,让后端增加接口代码。

getData.php代码如下:

<?php$t=isset($_GET['t'])?$_GET['t']:'num';$arr1=array('1','22','333','4444','55555');$arr2=array('a','bb','ccc','dddd','eeeee');if ($t=='num'){         $data=json_encode($arr1);         echo  'fn1('.$data.');';}else{         $data=json_encode($arr2);         echo  'fn2('.$data.');';}
              function fn1(data){  <!--声明全局函数 -->                      var  oUl1=document.getElementById('ul1');                      var   html='';                      for (vari=0;i<data.length;i++){                          html+= '<li>'+data[i]+'</li>';                      }                     oUl1.innerHTML=html;               }               function fn2(data){   <!--声明全局函数 -->                      var   oUl2=document.getElementById('ul2');                      var   html='';                      for (vari=0;i<data.length;i++){                          html+= '<li>'+data[i]+'</li>';                      }                     oUl2.innerHTML=html;               }

         <!-- <scriptsrc="getData.php"></script> 点击按钮时,动态创建 -->

<!-- 该标签中的文件getData.php中必须调用了上面定义的函数fn1fn2 -->

            <!-- RESTful API这种标准的数据格式,jsonp是不能访问的 -->          

window.onload = function() {             var oBtn1 =document.getElementById('btn1');                   var oBtn2 =document.getElementById('btn2');             oBtn1.onclick =function() {                       //当按钮点击的时候再去加载远程资源,让他执行                       var oScript = document.createElement('script');                       oScript.src = 'getData.php';                        document.body.appendChild(oScript);             }             //点击按钮2时也去请求一个资源             oBtn2.onclick = function() {                    /当按钮点击的时候再去加载远程资源,让他执行                    var oScript = document.createElement('script');                    oScript.src ='getData.php?t=str';                    document.body.appendChild(oScript);             }    }

     利用jsonp跨域请求资源<br>

    <input  type="button" id="btn1" value="加载数字"/>    <ul id="ul1"></ul>    <input type="button" id="btn2" value="加载字母"/>     <ul id="ul2"></ul>

常用的前后端交互方法:

前端将想要获得的函数名传递给后端,后端根据传入的函数名做动态匹配。

,将getData.php文件改为:

<pre name="code" class="php"><?php$t=isset($_GET['t'])?$_GET['t']:'num';$callback=isset($_GET['callback'])?$_GET['callback']:'fn1';$arr1=array('1','22','333','4444','55555');$arr2=array('a','bb','ccc','dddd','eeeee');if ($t=='num'){         $data=json_encode($arr1);    }else{                $data=json_encode($arr2);    }

//根据客户端传过来的参数callback,动态改变输出的函数名

echo$callback.'('.$data.');';

将前端对应的JS代码的第二个网址改为:getData.php?t=str?&callback=fn2

便可正常工作,这样即使想新添加接口也不用与后端沟通,便可实现自适应。

缺点:jsonp只能访问固定格式的资源,即如上例中定义在函数callback()中的数据。对于标准的RESTful API,jsonp是无法访问的。因此,考虑用那种方式获取资源时,应综合考虑后端返回的数据格式及先有方法的优缺点。

0 0
原创粉丝点击