關於JSONP

 三種方法造get請求

 

方法一:經過form表單請求和響應javascript

能夠post,刷新可經過iframe局部刷新css

 

index.htmlhtml

<!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發送請求java

直接在服務器中修改node

**此方法沒有辦法post,只能get,不安全ajax

 

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.jsjson

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
     }
 }
 })

 

待補充......

相關文章
相關標籤/搜索