JSONP

作者: 阿龙哟 | 来源:发表于2018-10-24 09:14 被阅读0次

能长久的存放数据就是数据库!

  if(path === '/'){
    var string = fs.readFileSync('./index.html','utf8')
    var amount = fs.readFileSync('./db','utf8')//同步读一个文件
    string=string.replace('&&&amount&&&',amount)
    可以用&&&amount&&&在HTML中当占位符,后端处理数据的时候替换掉这个占位符就行了
    response.setHeader('Content-Type', 'text/html; charset=utf-8')
    返回的也是一个页面 必须要设置好页面格式
    response.write(string)
    response.end()
  }else if( path === '/style.css'){
    var string = fs.readFileSync('./style.css','utf8')
    response.setHeader('Content-Type', 'text/css')
    response.write(string)
    response.end()
  }else if( path === '/main.js'){
    var string = fs.readFileSync('./main.js','utf8')
    response.setHeader('Content-Type', 'application/javascript')
    response.write(string)
    response.end()
  }else if(path === '/pay' && method.toUpperCase()==='POST'){
     var amount = fs.readFileSync('./db','utf8')//同步读一个文件
     var newAmount = amount - 1
     fs.writeFileSync('./db',newAmount)
     response.write('success!')
     response.end()
  }
  else{
    response.statusCode = 404
    response.setHeader('Content-type','text/html;charset=utf-8')
    response.write('找不到对应的路径')
    response.end()
  } 

html页面用form表单提交一个post请求,服务器改变数据再返回刷新到页面
一开始是用iframe在页面上显示改变数据,太古老,已经被众人忘记

想到用img创建请求 但是只能创建get请求
浏览器一旦发现img标签,就会发送一个请求,就是img的src

 let img = document.createElement('img')
      img.src = '/pay'
      img.onload = function () {
        alert('success')
        window.location.reload() //页面刷新
      }
      img.onerror = function () {
        alert('false')
      }

var amount = fs.readFileSync('./db','utf8')//同步读一个文件
     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('./1.jpg'))
     }
     else{
       response.statusCode = 400
       response.write('fail')
     }
     response.end()

onload加载成功 onerror 加载失败 因为假的图片骗不了浏览器必须要用一张真的图片

用状态码来判断是否请求成功


用script标签发送请求

button.onclick = function () {
      let script = document.createElement('script')
      script.src='/pay'
      document.body.appendChild(script)
      script.onload=function(){
        alert('success')
        amount.innerText = amount.innerText-1;
      }
      script.onerror=function(){
        alert('fail')
      }
    }
else if(path === '/pay'){
     var amount = fs.readFileSync('./db','utf8')//同步读一个文件
     var newAmount = amount - 1
     if(Math.random()>0.5){
       fs.writeFileSync('./db', newAmount)
       response.setHeader('Content-Type','application/javascript')
       response.statusCode = 200
       response.write(`alert('hehe') 
       amount.innerText = amount.innerText-1
       `)
     }
     else{
       response.statusCode = 400
       response.write('fail')
     }
     response.end()
  }

这样就可以不用使用 一张图片了,更加节省性能了
但是人们发现一件事,就是说如果成功了的话返回的script标签每次都会执行,所以就不用监听onload事件了,只需要监听onerror就可以了


image.png

优化

image.png

有人发现你不停的发送script请求,导致HTML里的script标签太多,怎么办,请求过后立即删除!

script.onload = function (e) {
        e.currentTarget.remove()
      }
      script.onerror = function (e) {
        alert('fail')
        e.currentTarget.remove()
      }

server rendered javascript 无刷新局部更新界面

get 请求不安全,如果没有防护措施,任何人都可以用一张图片,一个script标签去伪造请求,所以涉及到金钱等请求必须要用post

一个网站访问另一个网站的script

创建端口: PORT=8002 node server

修改hosts:
127.0.0.1 frank.com
127.0.0.1 jack.com
windows修改hosts
开启两个端口,一个8001,一个8002

用frank的前端访问Jack的后端


image.png
image.png

但是问题又来了


image.png

要解耦,服务端就执行你前端url里送过来的参数,函数在HTML中

 window.yyy = function (result) {
      if (result === 'success') {
        amount.innerText = amount.innerText - 1;
      } else {

      }
    }
    button.onclick = function () {
      let script = document.createElement('script')
      script.src = 'http://jack.com:8002/pay?callbackName=yyy'
      函数名包含在url中传输,callbackName  函数已经在前端写好了,这
      就解耦了,后端只要确认你执行哪个函数就行
      document.body.appendChild(script)
      script.onload = function (e) {
        e.currentTarget.remove()
      }
      script.onerror = function (e) {
        alert('fail')
        e.currentTarget.remove()
      }
    }
response.write(` 
       ${query.callbackName}.call(undefined,'{
         "success":true,
         "left":${newAmount}
       }')
       `)


什么是JSONP(自己理解)

后端响应前端最重要的就是这一块JSON,也有可能是对象,JSON和前后称为padding的部分合起来就是JSONP
JSON+padding = JSONP
大部分时间不一定是JSON,可能是String
那么就是'StringP'

image.png

什么是真正的JSONP

请求方:frank.com的前端程序员(浏览器)
响应方:Jack.com的后端程序员(服务器)
1.请求创建script,src指向响应方,同时传一个查询参数?callbackName=yyy
2.响应方根据查询参数callbackName,构造形如
1.yyy.call(undefined,'你要的数据')
2.yyy('你要的数据')
这样的响应
3.浏览器接到这样的响应,就会执行yyy.call(undefined,'你要的数据')
4.那么请求方就会知道了自己想要的数据
这就是JSONP

有两条规定:
1.回调callbackName统一规定为callback
2.函数名称为了不冲突覆盖 yyy改为随机数,例如frank123568454()


真正的JSONP写法

前台代码
  button.onclick = function () {
      let script = document.createElement('script')
      let functionName = 'frank' + parseInt(Math.random() * 1000000, 10)
      window[functionName] = function (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) {
        e.currentTarget.remove()
        delete window[functionName]
      }
      script.onerror = function (e) {
        alert('fail')
        e.currentTarget.remove()
        delete window[functionName]
      }
    }
  后台代码
   var amount = fs.readFileSync('./db', 'utf8') //同步读一个文件
    var newAmount = amount - 1
    fs.writeFileSync('./db', newAmount)
    response.setHeader('Content-Type', 'application/javascript')
    response.statusCode = 200
    response.write(` 
       ${query.callback}.call(undefined,'{
         "success":true,
         "left":${newAmount}
       }')
       `)
    //说明jack的后端要对frank的前端代码细节要很熟悉
    //解耦
    response.end()
image.png

jquery jsonp使用方式

  $.ajax({
              url: "http://jack.com:8002/pay",
              dataType: "jsonp",
              success: function (response) {
                if (response === 'success') {
                  amount.innerText = amount.innerText - 1;
                }
              }
              })

jquery帮忙省了很多工作,比如callback自动生成,函数名自动生成,但是一个很坑的地方在于JSONP跟AJAX一点关系都没有,它却把jsonp使用归结到了ajax方法了

千万记住这两者不同


面试题:请问jsonp为什么不支持post???

因为jsonp是通过动态创建script实现的,动态创建script的时候只能使用get不能使用post!!

同源策略:域名相同,协议相同,端口相同
AJAX默认的是同源策略,有三种方法实现跨域1.JSONP2.WebSocket3.CROS

相关文章

网友评论

      本文标题:JSONP

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