jsonp简单实现2

之前已经大概写了一下jsonp的简单的实现方式,今天来对其进行补充和优化,首先,先来总结一下实现jsonp的步骤:

  1. 将不同源的服务器端请求地址写在script标签的src属性中;
  2. 服务器端相应的数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数的参数
  3. 客户端全局作用域下定义函数fn(注:要写在请求地址前)
  4. 在fn内对服务器端返回的数据进行处理

然后我们就要对 上一节 的代码进行扩展和完善:
首先,我们想要把第一步写死的script标签动态生成,也就是在需要其的时候,再去创建他,不需要的时候就把他删除,我们来看看如何实现:

//jsonp.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!--点击按钮模拟请求-->
    <button id=”btn">点击发送请求</button>
    <script>
        function fn(){
             console.log("fn被调用")
        }
    </script>
    <!--动态生成标签的函数-->
    <script>
          var btn=document.getElementById("btn")
           btn.onclick=function(){
           //创建script标签
           var script=document.createElement("script")
           //设置src属性
           script.src="http://localhost:3001/test"
           //添加到页面中
           document.body.appendChild(script)
           }
    </script>
</body>
</html>

让我们先来看看结果执行结果
如图,当点击后服务器返回了和之前一样的结果,说明使其动态生成成功,可是这样有会产生一个问题,让我们先来看下面这张图片:
问题描述
可以看到我们在每次点击后,都会向html中添加一个请求的script标签,我们并不想这样,怎么修改呢?很简单,script标签下有一个onload事件,这个标签会在标签创建后调用,我们在其中将这个script标签删除即可,于是修改script代码为

 <script>
          var btn=document.getElementById("btn")
           btn.onclick=function(){
           //创建script标签
           var script=document.createElement("script")
           //设置src属性
           script.src="http://localhost:3001/test"
           //添加到页面中
           document.body.appendChild(script)
           //添加onload事件
           script.onload=function(){
               //删除标签
               document.body.removeChild(script)
             }
           }
    </script>

这样就不会再body中看到这个标签了。

然后再来看下一个想要优化的点,即函数名称问题,我们如果写代码时发现函数名字重复或者出错,我们就需要同时修改客户端和服务器端上相对应的函数名称,这样很麻烦,如何解决呢?
这里有一个方法即客户端将函数名传到服务器端,这样服务器端就可以直接用这个名字,我们进行以下修改:

script.src="http://localhost:3001/test?callback=fn"

即让函数名作为参数给到客户端,相应修改服务器端的代码:

app.get("/test",(req,res)=>{
    let fnName=req.query.callback;//获取传递过来的参数
    let fn=fnName+"()";
    res.send(fn)
})

再来尝试一下:
在这里插入图片描述
依然返回了正确的结果,这样,我们修改的话,只需要修改客户端函数名字就可以了,而不需要顾虑服务器端,减少了错误的发生率,很好。

再接着往下看,如果我们要发送多个请求的话,是不是每一次都需要写相同的代码呢?
为了解决这个问题,我们就要去封装一个函数,暂时就将这个函数的名称定为jsonp,如何实现呢,让我们看代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <!--点击按钮模拟请求-->
    <button id="btn">点击发送请求</button>
    <script>
    //   function fn() {
    //     console.log("fn被调用");
    //   }
    </script>
    <!--动态生成标签的函数-->
    <script>
      var btn = document.getElementById("btn");
      btn.onclick = function() {
        //创建script标签
        //设置src属性
        jsonp({
            url:"http://localhost:3001/test",
            success:function(){
               console.log("success被调用")
            }
        })
      };
      function jsonp(obj) {
        //创建script标签
        var script = document.createElement("script");
        //需要将其变成全局函数
        //防止请求覆盖生成一个随机名字
        var fnName="fn"+Math.random().toString().replace(".","");
        window[fnName]=obj.success
        //设置src属性
        script.src = obj.url+"?callback="+fnName;//不需要在关心函数名称问题
        //添加到页面中
        document.body.appendChild(script);
        script.onload = function() {
          //删除标签
          document.body.removeChild(script);
        };
      }
    </script>
  </body>
</html>

结果为结果
这样看起来是不是就舒服了很多。
这篇文章大概就说到这里,如有不足,可以再评论区留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值