关于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('请指定端口号\nnode 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('含查询字符串的路径\n' + pathWithQuery)

  console.log('HTTP路径为\n' + 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 + ' 成功\n 请打开 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('含查询字符串的路径\n' + pathWithQuery)

  console.log('HTTP路径为\n' + 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('含查询字符串的路径\n' + pathWithQuery)

  console.log('HTTP路径为\n' + 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('含查询字符串的路径\n' + pathWithQuery)

  console.log('HTTP路径为\n' + 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
     }
 }
 })

 

待补充......

posted @ 2019-07-16 12:57  BUBU_Sourire  阅读(265)  评论(0编辑  收藏  举报