JSONP理解和实现

作者: 飞天小猪_pig | 来源:发表于2021-08-30 16:36 被阅读0次
    JSONP的格式
    2021-08-22_110634.png
    JSONP 不支持 POST的原因
    • i、因为JSONP是通过创建script实现的
    • ii、动态创建script只能用get,不能用post
    简单理解什么是数据库

    1、文件系统是一种数据库 2、MySQL 是一种数据库
    只要能长久地存数据,就是数据库

    先了解服务器和网页是怎么样进行交互的,慢慢发展到利用JSONP的技术和结合jquery方便快捷实现,其中原理结合代码和注释理解,这里只展示最关键代码,具体完整代码看我给出的github链接

    1、前端页面请求和服务器响应

    前端页面:index.html
    需求:点击付款信息,账户余额就会减少

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>100</span></h5>
    <button id="button">付款1块钱</button>
    <script >
      button.addEventListener('click',(e)=>{
        let n=amount.innerText
        let number = parseInt(n,10)
        let newNumber=number-1
       amount.innerText=newNumber
      })
    </script>
    

    服务器:index.js

      if(path === '/'){  // 如果用户请求的是 / 路径
        var string = fs.readFileSync('./index.html')  
        response.setHeader('Content-Type', 'text/html;charset=utf-8')  
        response.end(string)   
      }else if(path === '/style.css'){   
        var string = fs.readFileSync('./style.css')
        response.setHeader('Content-Type', 'text/css')
        response.end(string)
      }else if(path === '/main.js'){  
        var string = fs.readFileSync('./main.js')
        response.setHeader('Content-Type', 'application/javascript')
        response.end(string)
      }else{  
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8') 
        response.end('找不到对应的路径,你需要自行修改 index.js')
      }
    

    这种请求,做的付款信息,当刷新页面时候,数据就会重新刷新。所以我们需要服务器这里需要添加数据库,由数据库进行读写数据,前端只是发起请求,服务器做出响应修改数据库内容。

    2、添加数据库db(也就是一种文件存储数据)

    前端页面:index.html

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>
    <button id="button">付款1块钱</button>
    <script >
      button.addEventListener('click',(e)=>{
        let n=amount.innerText
        let number = parseInt(n,10)
        let newNumber=number-1
        amount.innerText=newNumber
      })
    </script>
    

    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>这里先用&&&amount&&&代表占位符,响应时候再取得后台服务器数据库db的数据再替换。

    服务器:index.js

    if(path === '/'){  // 如果用户请求的是 / 路径
        var string = fs.readFileSync('./index.html','utf-8')
        var amount = fs.readFileSync('./db','utf-8')  
        string = string.replace('&&&amount&&&',amount)
        response.setHeader('Content-Type', 'text/html;charset=utf-8')  
        response.end(string)   
      }else if(path === '/style.css'){   
        var string = fs.readFileSync('./style.css')
        response.setHeader('Content-Type', 'text/css')
        response.end(string)
      }else if(path === '/main.js'){  
        var string = fs.readFileSync('./main.js')
        response.setHeader('Content-Type', 'application/javascript')
        response.end(string)
      }else{  
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8') 
        response.end('找不到对应的路径,你需要自行修改 index.js')
      }
    

    var amount = fs.readFileSync('./db','utf-8') 先读取数据库db数据
    string = string.replace('&&&amount&&&',amount)占位符替换成读到的数据

    上传到github完整的代码

    3、实现页面的局部刷新(优化用户体验1)
    方案一:用图片造 get 请求

    前端页面:index.html

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>
    <button id="button">付款</button>
    <script >
      button.addEventListener('click',(e)=>{
      let image=document.createElement('img')
       image.src='/pay'
       image.onload=function(){  // 状态码是 200~299 则表示成功
         alert('付款成功')
         amount.innerText=amount.innerText-1 //后台数据库成功修改后,成功则页面同步修改
       }
       image.onerror=function(){  // 状态码大于等于 400 则表示失败
         alert('付款失败')
       }
      })
    </script>
    

    image.onload=function(){ }通过状态码知道响应成功则执行里面代码
    image.onerror=function(){ }通过状态码知道响应失败则执行里面代码

    服务器:index.js(新增路径为/pay代码)

      else if (path === '/pay'){
        var amount = fs.readFileSync('./db','utf-8')  
        var newAmount=amount-1
         if(Math.random()>0.5){
           fs.writeFileSync('./db',newAmount)
           response.setHeader('Content-Type', 'image/jpg')
           response.statusCode=200
           response.write(fs.readFileSync('./dog.jpg'))
         }else{
          response.statusCode=400
           response.write('fail')
         }
        response.end()   
      }
    

    Math.random()随机生成一个在0-1之间的数据
    fs.writeFileSync('./db',newAmount)将新数据写进数据库db中
    response.statusCode=200状态码是为了识别数据是否改写成功
    response.write(fs.readFileSync('./dog.jpg'))用图片造 get 请求,需读出照片

    上传到github的完整代码

    方案二:用 script 造 get 请求

    前端页面:index.html

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>
    <button id="button">付款</button>
    <script >
      button.addEventListener('click',(e)=>{
       let script=document.createElement('script')
       script.src='/pay'
       document.body.appendChild(script)
       script.onload=function(e){  //onload事件是在script事件执行完触发
         e.currentTarget.remove()
       }
      //  script.onload=function(){  *这部分由服务器中index.js执行*
      //    amount.innerText=amount.innerText-1 
      //  }
       script.onerror=function(e){  // 状态码大于等于 400 则表示失败
         alert('付款失败')
         e.currentTarget.remove()
       }
      })
    </script>
    

    let script=document.createElement('script')动态创建一个script标签
    document.body.appendChild(script)这个script标签要挂在body下,image请求就不用,script请求就要(谨记)
    e.currentTarget.remove()响应不论成功和失败都要移除script标签

    服务器:index.js(新增路径为/pay代码)

    else if(path === '/pay'){
        var amount = fs.readFileSync('./db','utf-8')  
        var newAmount=amount-1
         if(Math.random()>0.5){
           fs.writeFileSync('./db',newAmount)
           response.setHeader('Content-Type', 'application/javascript')
           response.statusCode=200
           response.write(`
                amount.innerText=amount.innerText-1 
            `)
         }else{
          response.statusCode=400
           response.write('fail')
         }
        response.end()  
    

    response.write(` amount.innerText=amount.innerText-1 `)这部分前端页面是能读取到这个响应的,所以页面数据会刷新。

    上传到github的完整代码

    4、实现跨域访问(两个域名之间的访问)

    需求:http://fei.com访问http://jack.com的服务器(请求方给一个查询参数,响应方根据查询参数构造对应响应)

    1、用记事本打开 hosts文件(菜单->文件->定位到C:\Windows\System32\drivers\etc),修改hosts内容。
    hosts文件新增内容:
    127.0.0.1 fei.com
    127.0.0.1 jack.com

    打开两个git bash窗口,设置两个端口打开浏览器
    PORT=8001 node index.js http://fei.com:8001
    PORT=8002 node index.js http://jack.com:8002
    fei.com前端页面:

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>
    <button id="button">付款</button>
    <script >
     button.addEventListener('click',(e)=>{
       let script=document.createElement('script')
       let functionName='fei'+parseInt(Math.random()*100000,10)
       window[functionName]=function(result){
        // alert('我是fei.com写的代码')
        // alert(`我得到的结果是${result}`)
          if(result === 'success'){
             amount.innerText=amount.innerText-1
          }else{
    
           }
        }  
       script.src='http://jack.com:8002/pay?callback='+functionName
       document.body.appendChild(script)
       script.onload=function(e){  //onload事件是在script事件执行完触发
         e.currentTarget.remove()
         delete window[functionName]
       }
       script.onerror=function(e){  // 状态码大于等于 400 则表示失败
         alert('付款失败')
         e.currentTarget.remove()
         delete window[functionName]
       }
      })
    </script>
    

    1、let functionName='fei'+parseInt(Math.random()*100000,10)随机生产一个查询参数
    2、 script.src='http://jack.com:8002/pay?callback='+functionName 访问jack服务器,同时传给服务器一个查询参数
    3、delete window[functionName]最后运行完,要删除这个随机产生的查询参数

    jack.com后端服务器:

    else if(path === '/pay'){
        var amount = fs.readFileSync('./db','utf-8')  
        var newAmount=amount-1
         if(Math.random()>0.5){
           fs.writeFileSync('./db',newAmount)
           response.setHeader('Content-Type', 'application/javascript')
           response.statusCode=200
           response.write(`
               ${query.callback}.call(undefined,'success')
            `)
         }else{
           response.statusCode=400
           response.write('fail')
         }
        response.end()  
    

    ${query.callback}.call(undefined,'success')服务器查询传入的查询参数

    上传到github的完整代码

    5、利用jquery能快速实现完成跨域访问(两个域名之间的访问)

    fei.com前端页面:

    <title>首页</title>
    <link rel="stylesheet" href="/style.css">
    <h5>你的账户余额是:<span id='amount'>&&&amount&&&</span></h5>
    <button id="button">付款</button>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js'></script>
    <script >
      //用jquery能快速实现fei.com访问jack.com
      button.addEventListener('click',(e)=>{
        $.ajax({
        url: "http://jack.com:8002/pay",  //访问的地址需要输入
        jsonp: "callback",    
        dataType: "jsonp",
        success: function(result) {    //响应后需要进行处理输入
          if(result === 'success'){
             amount.innerText=amount.innerText-1
          }
        }
        });
    

    注意可以运用这个模板能快速实现跨域访问,注意里面写的ajax,用的不是ajax方法这个还是jquery的方法。

    上传到github的完整代码

    相关文章

      网友评论

        本文标题:JSONP理解和实现

        本文链接:https://www.haomeiwen.com/subject/yruzbltx.html