• jsonp原理


    首先我们要知道跨域是什么,又为什么要有跨域操作

    跨域是什么

    跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。

    好这里我们提炼出两个东西---1.同源策略:url首部的协议+域名+端口号必须一样,一者不同即为跨域

                                                  2.安全限制(这也是为什么需要跨域操作下一段介绍)

    为什么需要跨域操作/为啥需要同源策略/为什么要限制ajax跨域(面试可能会这样问)

    这个和cookie的存储原理有关(这里不介绍cookie),在生活里我们登录一个网站P(photoshop学习网站),然后他会存个通行证,下一次我们再上p站的时候

    它是不是就自动登录了,我们用别的网站去请求登录p是不是就登录不上。

    然后这个例子我们把它专业化一下下

    1.客户向p网站的服务器发送登录请求,携带账号密码数据

    2.P网站的服务器校验账号密码正确后,返回响应并给本地添加了Cookie

    3.之后客户再次向P网站发起请求会自动带上P网站存储在本地的cookie

    4.P网站的服务器从cookie中获取账号密码数据后,返回登陆成功界面。

    假如ajax请求可以跨域,那我是不是可以在这个博客里写一段js,使用ajax向你的学习网站发起登录请求,因为

    很多人的电脑上会存有学习网站的cookie不需要输入账号密码直接就自动登录了,再ajax回调函数中解析了返回的数据,

    我就能知道你学的是不是potoshop了。

    所以才需要同源策略,为了用户的信息安全也必须限制ajax的跨域操作

    ps:同源策略限制内容:(1)存储内容:cookie,localStorage,sessionStorage,(2)DOM节点

                                         (3)ajax请求,需注意ajax请求会发送出去,也会被返回,但会被浏览器拦截。

    不被限制的有img  link  script

    进入正题jsonp

     我们现在已经知道了能够不被同源限制的标签有img link script 那我们该选择哪个嘞?

    当然是script,只有这兄弟和代码有关嘛

    首先咱得整个服务器出来用 node模拟一下

    //服务端
    const http =require("http");//导入http模块
    http.createServer(
        (req,res) =>
        {
          let weather="四川 梅雨天";//客户端要访问的数据
          res.writeHead(200,{
            "Content-Type":"text/plain;charset=utf-8"
          });//防止乱码,用jq的Ajax就不需要,Ajax会自动识别
          res.write(weather);
          res.end();
    })
    .listen(3000);//3000端口

    然后在客户端写<script src="http://localhost:3000",会得到一个类型错误,因为js没法解析四川 梅雨天呀,这玩意儿都不是个语句,它笨解析不了

    也就是说我们要在res.write拼接一条语句传给客户端于是乎

    //服务端
    const http =require("http");
    http.createServer(
        (req,res) =>
        {
          let weather="四川 梅雨天";
          res.writeHead(200,{
            "Content-Type":"text/plain;charset=utf-8"
          });
          res.write(`("document.write(${weather}")`);
          res.end();
    })
    .listen(3000);

    然后再在客户端写<script src="http://localhost:3000",就发现页面上能打印出四川 梅雨天了,可是有个问题,我们的操作是不是写死了?那咱就在

    客户端整个操作有关的函数呗

      function  show(w) {
       alert(w);
      }
    </script>

    然后把服务器的res.write(`("document.write(${weather}")`);改成res.write(`("show(${weather}")`);嗯~ o(* ̄▽ ̄*)o可是又有问题了我要是想改函数是不是要改两个地方

    可不可以把这个函数整成动态的?可以的我们把函数的信息放到url的query里

    <script src="http://localhost:3000?callback=show">
    /*这里用callback接受函数信息,又因为本来show就是回调函数(相信大家体会出来了)所以用的callback命名,爱用啥都可以*/

    那么在服务器咋个取得callbck嘞

    onst http =require("http");
    const url=require("url");//引入url模块
    http.createServer(
        (req,res) =>
        {
          var Url=url.parse(req.url,true);
          var callback=Url.query.callback;//大概意思从url取到callback
          let weather="四川 梅雨天";
          res.writeHead(200,{
            "Content-Type":"text/plain;charset=utf-8"
          });
          res.write(`${callback}("${weather}")`);
          res.end();
        })
        .listen(3000);

    然后这个问题也解决了,但我们平时点一个按钮然后做跨域请求肯定不是这样把script标签写在外面浪费内存不说,代码还不美观

    所以终极的代码来了

    //客户端代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    </head>
    <body>
    <button>天气预报</button>
    <script>
      let click=document.querySelector("button");
      click.addEventListener("click",()=>{
        let script=document.createElement("script");
        script.src=`http://localhost:3000/?callback=show`;
        document.body.appendChild(script)
      });//对按钮添加点击事件在body里生产script
      function  show(w) {
        alert(w);
        document.body.lastChild.remove();//对每次生成的script在结束后移除
      }
    </script>
    </body>
    </html>
    //服务器代码不变

    好了以上就是jsonp的原理总结一下,(1)声明一个回调函数,其函数名(如show)当做参数值,要传递给跨域请求数据的服务器,

                                                                        函数形参为要获取目标数据(服务器返回的data)。

                                                               (2)创建一个<script>标签,把那个跨域的API数据接口地址,赋值给script的src,

                                                                        还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show)。

                                                               (3)服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,

                                                               (4)最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(show),

                                                                         对返回的数据进行操作

    所以jsonp是一种思想每个人写的jsonp可能都会不一样,但终终极方案JQubiery里ajax请求里写 dataType : "jsonp",完事儿了,但思想还是要理解的。

     

  • 相关阅读:
    python连接集群mongodb,封装增删改查
    selenium截屏操作(也支持截长图)
    ant生成jmeter测试报告没有数据【已解决】
    论自动化如何提高测试工作效率
    研究显示情商高的人比智商高的可怕多了
    提高程序员职场价值的10大技巧
    革命就是请客吃饭(案例分析吧)
    开发者应该了解的API技术清单!
    陈天:如何快速掌握一门技术
    程序员如何参与创业
  • 原文地址:https://www.cnblogs.com/jiangxiaoming/p/13657929.html
Copyright © 2020-2023  润新知