• 关于JSONP


     三种方法造get请求

    方法一:通过form表单请求和响应

    可以post,刷新可通过iframe局部刷新

    index.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">
        <link rel="stylesheet" href="style.css">
        <title>button</title>
    </head>
    
    <body>
        <h5>您的账户余额是 <span id="amount">&&amount&&</span></h5>
    
        <form action="/pay" method="POST" target="result">
        <!-- post方法 -->
            <input type="submit" name="number" value="付款">
        </form>
        <iframe name="result" src="about:blank" frameborder="0" height="100"></iframe>
        <!-- 一个老办法 在iframe中承载刷新 -->
    
    </body>
    
    </html>

    server.js

    var http = require('http')
    var fs = require('fs')
    var url = require('url')
    var port = process.argv[2]
    
    if (!port) {
      console.log('请指定端口号
    node server.js 8888 ')
      process.exit(1)
    }
    
    var server = http.createServer(function (request, response) {
      var parsedUrl = url.parse(request.url, true)
      var pathWithQuery = request.url
      var queryString = ''
      if (pathWithQuery.indexOf('?') >= 0) { queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
      var path = parsedUrl.pathname
      var query = parsedUrl.query
      var method = request.method
    
      /********************/
    
      console.log('含查询字符串的路径
    ' + pathWithQuery)
    
      console.log('HTTP路径为
    ' + path)
      if (path == '/') {
        var string = fs.readFileSync('./index.html', 'utf8')
        var amount = fs.readFileSync('./db', 'utf8')//同步读取db这个文件,其中内容的值是100,类型是字符串
        string = string.replace('&&amount&&', amount)//&&amount&&为占位符
        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//amount是字符串类型,-1后自动转成数字类型
        fs.writeFileSync('./db',newAmount)//将newAmount存到db中
        response.write('success')//告知成功
        response.end()
      } else {
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8')
        response.write('找不到对应的路径,需自行修改')
        response.end()
      }
    
      /*******************/
    })
    
    server.listen(port)
    console.log('监听 ' + port + ' 成功
     请打开 http://localhost:' + port)

    方法二:通过image发送请求

    直接在服务器中修改

    **此方法没有办法post,只能get,不安全

    index.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">
        <link rel="stylesheet" href="style.css">
        <title>button</title>
    </head>
    
    <body>
        <h5>您的账户余额是 <span id="amount">&&amount&&</span></h5>
        <button id="button">支付</button>
        <script src="main.js"></script>
    </body>
    
    </html>

    main.js

    button.addEventListener('click', (e) => {
    let image = document.createElement('img') image.src = '/pay' //告知用户请求成功 image.onload = function () { alert('打钱成功') amount.innerText = amount.innerText - 1 //成功则自动减一 } //告知用户请求失败 image.onerror = function () { alert('打钱失败') } })

    server.js

    /*******************/
    console.log('含查询字符串的路径
    ' + pathWithQuery)
    
      console.log('HTTP路径为
    ' + path)
      if (path == '/') {
        var string = fs.readFileSync('./index.html', 'utf8')
        var amount = fs.readFileSync('./db', 'utf8')//同步读取db这个文件,其中内容的值是100,类型是字符串
        string = string.replace('&&amount&&', amount)//&&amount&&为占位符
        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') {
        var amount = fs.readFileSync('./db', 'utf8')//读取当前数据库中存储的数据
        var newAmount = amount - 1//amount是字符串类型,-1后自动转成数字类型
        //模拟支付失败
        if (Math.random() > 0.5) {
          fs.writeFileSync('./db', newAmount)//将newAmount存到db中
          response.setHeader('Content-Type', 'image/png')
          response.statusCode = 200//返回状态码200告知浏览器请求可以,从而告知用户支付成功
          response.write(fs.readFileSync('./1.png'))//给浏览器一个实质的图片以避免浏览器不接受图片的请求
        } else {
          response.statusCode = 400//同理反之
          response.write('fail')
        }
        response.end()
      } else {
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8')
        response.write('找不到对应的路径,需自行修改 index.js')
        response.end()
      }
    /*******************/

    方法三:通过script发送请求

    SRJ

    server rendered javascript 服务器返回javascript

    只有get没有post

    <!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">
        <link rel="stylesheet" href="style.css">
        <title>button</title>
    </head>
    
    <body>
        <h5>您的账户余额是 <span id="amount">&&amount&&</span></h5>
        <button id="button">支付</button>
        <script src="main.js"></script>
    </body>
    
    </html>

    main.js

    button.addEventListener('click', (e) => {
        let script = document.createElement('script')
        script.src='/pay'
        document.body.appendChild(script)
        script.onload=function(e){
            e.currentTarget.remove()//删除每次点击执行时生成的script
        }
        script.onerror=function(e){
            alert('fail')
            e.currentTarget.remove()//同上删除script
        }
    })

    server.js

    /********************/
    
      console.log('含查询字符串的路径
    ' + pathWithQuery)
    
      console.log('HTTP路径为
    ' + path)
      if (path == '/') {
        var string = fs.readFileSync('./index.html', 'utf8')
        var amount = fs.readFileSync('./db', 'utf8')//同步读取db这个文件,其中内容的值是100,类型是字符串
        string = string.replace('&&amount&&', amount)//&&amount&&为占位符
        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') {
        var amount = fs.readFileSync('./db', 'utf8')//读取当前数据库中存储的数据
        var newAmount = amount - 1//amount是字符串类型,-1后自动转成数字类型
        //模拟支付失败
        if (Math.random() > 0.5) {
          fs.writeFileSync('./db', newAmount)//将newAmount存到db中
          response.setHeader('Content-Type', 'application/javascript')
          response.statusCode = 200//返回状态码200告知浏览器请求可以,从而告知用户支付成功
          response.write(`
          alert("success")
          amount.innerText=amount.innerText-1
          `)//服务器返回了在浏览器执行的代码
        } else {
          response.statusCode = 400//同理反之
          response.write('faile')
        }
        response.end()
      } else {
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8')
        response.write('找不到对应的路径,需自行修改 index.js')
        response.end()
      }
    
      /********************/

    模拟两个网站之间通过SRJ交流

    8001调用8002的数据库

    修改main.js

    button.addEventListener('click', (e) => {
        let script = document.createElement('script')
        script.src='http://localhost:8002/pay'
        document.body.appendChild(script)
        script.onload=function(e){
            e.currentTarget.remove()//删除每次点击执行时生成的script
        }
        script.onerror=function(e){
            alert('fail')
            e.currentTarget.remove()//同上
        }
    })

    关于耦合和解耦

    后端代码里面有前端的js代码,这个是对前端按钮的细节处理,这叫耦合

    解决这个问题叫解耦

     

    完整代码:

    index.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">
        <link rel="stylesheet" href="style.css">
        <title>button</title>
    </head>
    
    <body>
        <h5>您的账户余额是 <span id="amount">&&amount&&</span></h5>
        <button id="button">支付</button>
        <script src="main.js"></script>
    </body>
    
    </html>

    main.js

    button.addEventListener('click', (e) => {
        let script = document.createElement('script')
        let functionName='callcall'+parseInt(Math.random()*100000,10)//随机函数名,避免污染全局变量,用完就delete
    
        window[functionName]=function(result){
            if(result==='success'){
                alert('支付成功')
                amount.innerText=amount.innerText-1
            }else{
    
            }
         }
    
        script.src='http://localhost:8002/pay?callback='+functionName//约定:这里的callbackName为callback
        document.body.appendChild(script)
        script.onload=function(e){
            e.currentTarget.remove()//删除每次点击执行时生成的script
            delete window[functionName]//随机函数只用一次,用完就去掉
        }
        script.onerror=function(e){
            alert('支付失败')
            e.currentTarget.remove()//同上
            delete window[functionName]
        }
    })

    server.js

     /********************/
    
      console.log('含查询字符串的路径
    ' + pathWithQuery)
    
      console.log('HTTP路径为
    ' + path)
      if (path == '/') {
        var string = fs.readFileSync('./index.html', 'utf8')
        var amount = fs.readFileSync('./db', 'utf8')//同步读取db这个文件,其中内容的值是100,类型是字符串
        string = string.replace('&&amount&&', amount)//&&amount&&为占位符
        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') {
        var amount = fs.readFileSync('./db', 'utf8')//读取当前数据库中存储的数据
        var newAmount = amount - 1//amount是字符串类型,-1后自动转成数字类型
        //模拟支付失败
        if (Math.random() > 0.5) {
          fs.writeFileSync('./db', newAmount)//将newAmount存到db中
          response.setHeader('Content-Type', 'application/javascript')
          response.statusCode = 200//返回状态码200告知浏览器请求可以,从而告知用户支付成功
          response.write(`
          ${query.callback}.call(undefined,'success')
          `)//*********此处解耦,后端将前端传的参数放在call前面********
        } else {
          response.statusCode = 400//同理反之
          response.write('fail')
        }
        response.end()
      } else {
        response.statusCode = 404
        response.setHeader('Content-Type', 'text/html;charset=utf-8')
        response.write('找不到对应的路径,需自行修改 index.js')
        response.end()
      }
    
      /********************/

    总结JSONP

    为什么叫JSONP?(了解一下)

    json+padding -- JSONP

    JSONP的实质?

    JSONP解决两个网站之间的交流,即利用动态标签进行跨域请求。(用script标签,script标签不受域名限制,AJAX受域名限制)

    详述:

    请求方:浏览器(某网前端)

    响应方:服务器(另某网后端)

    1.请求方创建script,src指向响应方,同时传一个查询参数?callback=随机数xxx(约定)

    2.响应方根据查询参数callback,构造形如

      随机数xxx.call(undefined,'要的数据')

      这样的响应

    3.浏览器接收到响应,就会执行随机数xxx.call(undefined,'要的数据')

    4.请求方得到要的数据

    为什么JSONP不能支持POST请求?

    1.JSONP是通过动态创建script实现的

    2.动态创建script时只能用get,没办法用post

    用Jquery实现JSONP

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

    待补充......

  • 相关阅读:
    理解C#中的 async await
    kube-proxy IPVS 模式的工作原理
    Kilo 使用教程
    Wireguard 全互联模式(full mesh)配置指南
    我为什么不鼓吹 WireGuard
    iTerm2 实现 ssh 自动登录,并使用 Zmodem 实现快速传输文件
    在 Docker Desktop 中启用 K8s 服务
    ABP 适用性改造
    ABP 适用性改造
    在 ASP.NET Core 应用中使用 Cookie 进行身份认证
  • 原文地址:https://www.cnblogs.com/BUBU-Sourire/p/11192227.html
Copyright © 2020-2023  润新知