解决浏览器跨域问题

参考以下几条

(8条消息) 简单的跨域案例_sleepwalker_1992的专栏-CSDN博客

(8条消息) jsonp的使用,解决跨域资源引起CORB问题_D_R_L_T的博客-CSDN博客

(9条消息) 轻松搞定JSONP跨域请求_诗渊的博客-CSDN博客_jsonp

JSONP原理及实现 - 简书 (jianshu.com)

jQuery jsonp跨域请求 - bojiangzhou - 博客园 (cnblogs.com)

跨域的实现与前端和服务器端都有关,根据服务端返回数据的类型而不同前端处理也不同

经过测试,服务端不同,返回数据不同,有json格式,有js对象格式,有的需要跨域,而有的不需要配置跨域就可以访问,下面列举了一些例子

例子一:返回json格式

访问失败

例子二:返回js对象格式

访问失败

对于返回json格式的数据,服务器不支持跨域,前端也没有办法实现,所以跨域是需要前后端同时支持的

jsonp

jsonp是一种跨域解决方式

其原意是指在json数据两端加一个括号前面加一个名称把json封装成一个对象来解决跨域问题

假设客户期望返回数据:["customername1","customername2"]。

真正返回到客户端的数据显示为: callbackFunction(["customername1","customername2"])。

一般来说大多数api都已经支持跨域,请求在请求连接后加上&cb(&callback)变量名就会返回一个js对象

实现有两种

1.例如上面的淘宝

这种是返回jsonp,绝大多数是这种

2.这种是返回一个js变量,这种很少

对于这种的实现方式是

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const script = document.createElement("script");
      //2 设置标签的src属性
      script.src = "http://hq.sinajs.cn/list=sh601006";
      //3 将script插入文档中
      document.body.appendChild(script);
      console.log("before onload")
      window.onload = function () {
        console.log("after onload")
        console.log(hq_str_sh601006);
      };
    </script>
  </body>
</html>

原理是引入标签后,在文档中创建了名为hq_str_sh601006的js变量,直接调用即可

前端jsonp实现跨域

本文只针对前端实现跨域,有多种方式,后端默认为jsonp如上的第一种

script实现原生jsonp

这个原理是创建了一个js对象,像函数一样调用即可

 

这里有多种写法,我还没摸清楚是什么原理

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const script = document.createElement("script");
      script.src = "https://suggest.taobao.com/sug?q=520&callback=haha";
      document.body.appendChild(script);

      window["haha"] = function (data) {
        console.log("写法1");
        console.log(data);
      };
       window.haha=function(res) {
         console.log("写法2");
         console.log(res);
       };
       function haha(data){
         console.log("写法3");
         console.log(data);
       }
    </script>
  </body>
</html>

jq实现jsonp

jq实现script jsonp

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Document</title>
  </head>
  <body>
    <script>
      $(document).ready(function () {
        // 向头部输入一个脚本,该脚本发起一个跨域请求
        $("head").append(
          "<script src='https://suggest.taobao.com/sug?q=520&callback=haha'><\/script>"
        );
      });
      function haha(data) {
        console.log(data);
      }
    </script>
  </body>
</html>

jq实现jsonp

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Document</title>
  </head>
  <body>
    <script>
      $(document).ready(function () {
        $.ajax({
          url: "https://suggest.taobao.com/sug?q=520",
          //也可以像下面这样写,jq会自动在后面加上callback,?后面会自动生成函数名
          //url: "https://suggest.taobao.com/sug?q=520&callback=?",
          //而对于请求名不是callback的api不能这样写,要替换掉callback,如下api的请求名是cb
          //url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=ccf&cb?"
          type: "GET",
          dataType: "jsonp", //指定服务器返回的数据类型
          success: function (data) {//自动执行
            console.log(data);
          },
        });
      });
    </script>
  </body>
</html>

设置回调函数,这样就不会自动生成了,发出去的请求就是callback=showdata

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Document</title>
  </head>
  <body>
    <script>
      function showData(data) {
        console.log(data);
      }
      $(document).ready(function () {
        $.ajax({
          url: "https://suggest.taobao.com/sug?q=520",
          type: "GET",
          dataType: "jsonp", //指定服务器返回的数据类型
          jsonpCallback: "showData", //指定回调函数名称
          success: function (data) {//自动执行
            console.log(data);
          },
        });
      });
    </script>
  </body>
</html>

需要注意的是回调函数会执行,sucess也会执行,总之success是一定会执行的

所有的参数有

$.ajax({
                async : true,
                url : "https://api.douban.com/v2/book/search",
                type : "GET",
                dataType : "jsonp", // 返回的数据类型,设置为JSONP方式
                jsonp : 'callback', //指定一个请求名来覆盖默认的请求名callback
                jsonpCallback: 'handleResponse', //设置回调函数名
                success: function(response, status, xhr){
                    console.log('状态为:' + status + ',状态是:' + xhr.statusText);
                    console.log(response);
                }
            });

jq的简单方式

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <title>Document</title>
  </head>
  <body>
    <script>
      $.getJSON("https://suggest.taobao.com/sug?q=520&callback=?",
        function (data) {
          console.log(data);}
      );
    </script>
  </body>
</html>

封装一个完整jsonp

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>提示词</title>
  </head>
  <body>
    <script>
      function JSONP({ url, params, callbackKey, callback }) {
        // 唯一 id,不存在则初始化
        JSONP.callbackId = JSONP.callbackId || 1;
        params = params || {};
        // 传递的 callback 名,和下面预留的一致
        params[callbackKey] = `JSONP.callbacks[${JSONP.callbackId}]`;
        // 不要污染 window
        JSONP.callbacks = JSONP.callbacks || [];
        // 按照 id 放置 callback
        JSONP.callbacks[JSONP.callbackId] = callback;
        const paramKeys = Object.keys(params);
        const paramString = paramKeys
          .map((key) => `${key}=${encodeURIComponent(params[key])}`)
          .join("&");
        // const paramString = paramKeys
        //   .map((key) => `${key}=${params[key]}`)
        //   .join("&");
        const script = document.createElement("script");
        script.setAttribute("src", `${url}?${paramString}`);
        document.body.appendChild(script);
        // id 占用,自增
        JSONP.callbackId++;
      }
      JSONP({
        url: "https://suggest.taobao.com/sug",
        params: {
          q: "520",
        },
        callbackKey: "callback",
        callback(result) {
          console.log(result);
        },
      });
      JSONP({
        url: "https://suggest.taobao.com/sug",
        params: {
          q: "1314",
        },
        callbackKey: "callback",
        callback(result) {
          console.log(result);
        },
      });
    </script>
  </body>
</html>

请求成功后的处理

虽然返回的是一个函数可以直接执行,但是一般传的是json数据,所以可以转换为json

var result = JSON.stringify(data);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值