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理解和实现

    JSONP的格式 JSONP 不支持 POST的原因 i、因为JSONP是通过创建script实现的 ii、动态创...

  • 手写一个JSONP(promise封装)

    前言 JSONP以前研究过,最近又有点忘了,写篇本文mark一下,旨在理解记住JSONP的原理及其实现。代码实现用...

  • 前端跨域请求原理及实践

    一、 跨域请求的含义 2.3 使用 标签原生实现 JSONP 经过上面的事件,你是不是觉得 JSONP 的实现和...

  • 前端跨域请求原理及实践

    一、 跨域请求的含义 2.3 使用 标签原生实现 JSONP 经过上面的事件,你是不是觉得 JSONP 的实现和...

  • 实现跨域的方法

    不同域下的接口获取数据,可以使用jsonp和cors。(ie10以下可以使用jsonp获取数据) jsonp实现跨...

  • jsonp基础原理

    jsonP实现的效果和ajax非常类似,但jsonP并不是ajax的一部分。 jsonP主要用于解决跨站数据请求,...

  • jsonp原理和实现

    是时候彻底搞清jsonp了! jsonp主要是利用了脚本不受 同源策略 限制的"BUG",算是一种简单的hack写...

  • vue音乐APP03:jsonp promise化

    1.JSONP的用途和原理 使用JSONP主要是目的通过动态创建Script,动态拼接url,进而抓取数据,实现跨...

  • day02-vuejs-vue-resource实现get, p

    vue-resource实现get, post, jsonp]请求: JSONP的实现原理: 由于浏览器的安全性限...

  • jsonp理解

    1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、...

网友评论

    本文标题:JSONP理解和实现

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