亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JSONP技術(shù)棧

zsy888 / 970人閱讀

摘要:表單發(fā)請求付款在服務(wù)器里面增加一個請求路徑。動態(tài)創(chuàng)建方法發(fā)送請求叫做方案全稱,在出來以前,無刷新局部更新頁面內(nèi)容的最好的方案。

簡單的前后端交互

前面學(xué)習(xí)了這么多,都是在和頁面打交道,不管是HTML、CSS、JavaScript,DOM,都沒有跑出瀏覽器,那今天來學(xué)習(xí)下和后臺交互。

當(dāng)我點擊付款按鈕時,頁面的數(shù)值會減?。划?dāng)我刷新頁面時,內(nèi)容不會改變,該怎么實現(xiàn)呢?

先寫一個簡單的node.js腳本,讓頁面能夠正常運行

創(chuàng)建一個文件夾里面創(chuàng)建兩個文件

新建一個腳本文件

新建一個index.html文件

打開服務(wù)器,就可以看到自己的頁面了

腳本文件
  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


  /******** 從這里開始看,上面不要看 ************/

  if(path === "/"){
    var string = fs.readFileSync("./index.html","utf8")
    response.setHeader("Content-Type","text/html;charset=utf-8")
    response.write(string)
    response.end()
  }else if(path === "/css/style.css"){
    var string = fs.readFileSync("./css/style.css","utf8")
    response.setHeader("Content-Type","text/css")
    response.write(string)
    response.end()
  }else if(path === "/js/main.js"){
    var string = fs.readFileSync("./js/main.js","utf8")
    response.setHeader("Content-Type","text/javascript;charset=utf-8")
    response.write(string)
    response.end()
  }else{
    response.statusCode = 404
    response.setHeader("Content-Type","text/html;charset=utf-8")
    response.end("找不到對應(yīng)的路徑,你需要自行修改 index.js")
  }
  
  /******** 代碼結(jié)束,下面不要看 ************/
})

server.listen(port)
console.log("監(jiān)聽 " + port + " 成功
請用在空中轉(zhuǎn)體720度然后用電飯煲打開 http://localhost:" + port)
HTML 文件



    首頁


    
你的余額是100

當(dāng)我們點付款的時候,100會往下減小,但是當(dāng)我們刷新頁面的時候,又變成了100。

這里我們只是在瀏覽器上面操作頁面內(nèi)容,數(shù)據(jù)沒有長久的存儲在數(shù)據(jù)庫里面,所以當(dāng)我們刷新頁面時,它又回到初始狀態(tài),這顯然不是我們要的效果。

我們該怎么解決這個問題呢?

用占位符替換頁面數(shù)據(jù)

我們在剛才的當(dāng)前文件夾中新建一個文件,作為我們的數(shù)據(jù)庫,現(xiàn)在我們把100元寫在數(shù)據(jù)庫里。

數(shù)據(jù)庫簡單的講就是一個能長久存儲數(shù)據(jù)的地方,文件是數(shù)據(jù)庫最簡單的形式。

touch db
echo "100" > db

index.html中的100用一個占位符替代,這個占位符要和頁面中其他變量不重復(fù),實際上頁面上的數(shù)據(jù),前端是不需要知道的,用一個占位符站位即可,發(fā)送請求,后端程序員去讀數(shù)據(jù)庫里的內(nèi)容,返回給前端。

&&&amount&&&

在腳本中if(path === "/index.html")里加一個替換占位符語句。

var amount = fs.readFileSync("./index","utf8")        //文件中的數(shù)據(jù)類型是String
string = string.replace("&&&amount&&&",amount)

重啟服務(wù)器后,刷新頁面后我們看到的100是數(shù)據(jù)庫里的數(shù)據(jù),當(dāng)我們點擊付款時,變化的是數(shù)據(jù)庫里面的數(shù)據(jù),和前端沒有關(guān)系,但是當(dāng)我們刷新頁面后,依舊回到初始狀態(tài),沒有保存最新的數(shù)據(jù)。

我點付款的時候應(yīng)該發(fā)送一個請求告訴服務(wù)器,請把數(shù)據(jù)庫里的100變成99,然后刷新頁面;我不對頁面做操作改變它的數(shù)據(jù)了,那我點付款的時候,發(fā)起一個請求,應(yīng)該怎么做呢?

可以發(fā)請求的標(biāo)簽有img、link、script、form表單,當(dāng)我們點擊按鈕應(yīng)該發(fā)送POST請求,因為是更新數(shù)據(jù)庫內(nèi)容,所以這里只有form表單能發(fā)送POST請求。

form表單發(fā)請求

在服務(wù)器里面增加一個/pay請求路徑。

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

當(dāng)我點付款的時候,會看當(dāng)前頁面會跳轉(zhuǎn)到/pay路徑下的頁面,表示成功了。

點擊瀏覽器的返回上一頁,刷新下當(dāng)前頁面,之前的100變成了99,無論怎么刷新或者重新打開,數(shù)據(jù)都是之前的操作過結(jié)束后的數(shù)據(jù)。

這里前端要寫的就是form表單,后端如果發(fā)現(xiàn)是某個路徑并且是POST請求,就去操作數(shù)據(jù)庫。

這是舊時代的操作,form表單一旦提交了都會刷新當(dāng)前頁面,給用戶造成了不好的體驗。有個程序員想出了用iframe解決頁面刷新的問題,操作成功后在iframe打卡跳轉(zhuǎn)頁面。

iframe 表單刷新頁面

有個程序員覺得頁面中多出一個東西總是怪怪的,絞盡腦汁又想出了動態(tài)創(chuàng)建img標(biāo)簽的方法

動態(tài)創(chuàng)建img標(biāo)簽發(fā)送請求

有潔癖的程序員總是能想出更好的解決方法,接著來看下動態(tài)創(chuàng)建img標(biāo)簽的發(fā)送請求的方法。

腳本中增加/pay路徑下應(yīng)該這樣寫

 if(path === "/pay"){
      var string = fs.readFileSync("./db","utf8")
    var newAmount = string - 1
    if(Math.random() > 0.5){
        fs.writeFileSync("./db",newAmount)
        response.setHeader("Content-type","image/jpeg")
        response.statusCode = 200
        response.write(fs.readFileSync("./1.jpeg"))
    }else{
        response.statusCode = 400
        response.write("alert("fail")")
    }
    response.end()
  }

因為img標(biāo)簽,只能發(fā)送GET請求,所以這里就不做method判斷了。

JS 文件

button.addEventListener("click",function(e){
    let image = document.createElement("img")
    image.src = "/pay"
    img.onload = function(){
        alert("success")
        window.location.reload()
    }
    img.onerror = function(){
        alert("fail")
    }
})

onloadonerror是提示用戶成功了還是失敗,在onload里面加上一個window.location.reload()成功后會自動刷新頁面。

動態(tài)創(chuàng)建img標(biāo)簽的方法,必須要返回真實的圖片,瀏覽器才能知道操作成功了,不然onload一直不會成功,雖然數(shù)據(jù)庫已經(jīng)修改成功了,但瀏覽器只要沒接收到圖片,就會執(zhí)行onerror,這也是它的局限所在——必須要返回真是圖片。

同時刷新頁面會造成瀏覽器重新渲染,所以當(dāng)瀏覽器接收到響應(yīng)時,前端應(yīng)該在頁面上自動減1,用戶并不會知道這中間發(fā)生了什么。

動態(tài)創(chuàng)建script標(biāo)簽——SRJ方案

a標(biāo)簽發(fā)送請求太浪費資源了,這時又有人想出了用script標(biāo)簽發(fā)請求,這就是優(yōu)秀程序員和普通程序員之間的差距啊。

下面來看看是怎么實現(xiàn)的:

button.addEventListener("click",function(){
    var script = document.createElement("script")
    script.src = "/pay"
    document.body.appendChild(script)    //必須要將創(chuàng)建出來的Script放在頁面中才可以
    script.onload = function(){
        alert("sucess")
    }
})

/pay路徑下的代碼

if(path === "/pay"){  
      var string = fs.readFileSync("./db","utf8")
    var newAmount = string - 1
    fs.writeFileSync("./db",newAmount)
    response.setHeader("Content-type","application/js")
    response.statusCode = 200
    response.write("alert("success1")")
    response.end()
  }

當(dāng)我點付款時,成功后首先執(zhí)行腳本里面的script,執(zhí)行完了之后才執(zhí)行main.js內(nèi)的onload。

因為腳本中的script先執(zhí)行,所以main.js里面就不需要提示用戶了,直接后臺給提示內(nèi)容就可以了。

如下:

response.write(`alert("success")
amount.innerText = amount.innerText -1`)    //ES6字符串方法

到這里聰明的你應(yīng)該也發(fā)現(xiàn)了一個問題,當(dāng)我點付款時,不管成功與否都會創(chuàng)建一個script,對于程序員來說是無法接受的,所以要用onloadonerror去監(jiān)聽,不管成功與否都將它刪除掉。這里雖然刪掉了但它還是在內(nèi)存中。

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

動態(tài)創(chuàng)建script方法發(fā)送請求叫做——SRJ方案(全稱 Server rendered javascript),在 ajax 出來以前,無刷新局部更新頁面內(nèi)容的最好的方案。

請求另一個網(wǎng)站的script

在頁面中引入一個script時,一定要在當(dāng)前域名嗎?

NO?。。∥覀冊陧撁嬷幸氲母鞣N庫,不都是引入別人的網(wǎng)站的script

那這樣的話,是不是可以操作別人網(wǎng)站的/pay,所以GET請求太不安全,太容易偽造了,所以大部分的/pay都用POST請求去做。

PORT=8002 node index.js 可以開多個端口

SRJ方案前后端耦合太緊密了,需要后端對頁面了解太清楚。

其實前端提供一個xxx() API就可以了。

response.write(`
xxx.call(undefined,"success")
`)

前端提供 API 的方法,其實解耦還沒有解的很干凈,我們在設(shè)置scriptsrc時可以直接設(shè)置請求參數(shù),腳本只需要取這個參數(shù)就可以了,至于具體叫什么名字不重要

script.src = "http://baidu.com:8002/pay?callbackName=xxx"
response.write(`
    ${query.callbackName}.call(undefined,"success")
`)

到這里已經(jīng)是很好的方案了,但是有一個問題是,調(diào)用函數(shù)傳遞的參數(shù),前端怎么知道呢?如果不確定,到時候出了問題就要各自扯皮了,這時候JSON應(yīng)運而出。

JSONP方案

JSONPJSON的格式進行參數(shù)傳遞,解決了兩個網(wǎng)站之間的交流。至于為什么叫JSONP,應(yīng)該是大括號左邊的叫做左padding,右邊的叫做右padding,連接起來就叫做JSONP。

${query.callbackName}.call(undefined,{
    "success": true
    "left": ${newAmount}
})
用文字?jǐn)⑹?JSONP

請求方:qq.com的前端程序員(瀏覽器)
響應(yīng)方:baidu.com的后端程序員(服務(wù)器)

請求方創(chuàng)建script ,src指向相應(yīng)方同事傳一個查詢參數(shù) ?callbackName=xxx

響應(yīng)方根據(jù)查詢參數(shù)callbackName,構(gòu)造形如xxx.call(undefined,"你要的數(shù)據(jù)")這樣的響應(yīng)

瀏覽器接收到響應(yīng),xxx.call(undefined,"你要的數(shù)據(jù)")

那么請求方就知道了它要的數(shù)據(jù)

這就是JSONP

約定:

callbackName -> callback

xxx -> 隨機數(shù)

按照約定寫一下

button.addEventListener("click",funcion(e){
    let script = document.createElement("script")
    let functionName = parseInt(Math.random()*1000000)        //這個函數(shù)名是隨機數(shù)
    window[functionName] = function(result){    //result是服務(wù)器返回的結(jié)果
        if(result === "success"){
            amount.innerText = amount.innerText - 1
        }
    }

    script.src = "http://baidu.com:8002?callback=" + functionName    //寫在參數(shù)里面
    document.body.appendChild(script)
    script.onload = function(e){
        e.currentTarget.remove()
        delete window[functionName]    //如果成功了要干掉這個函數(shù)
    }
    script.onerror = function(e){
        alert("false")
        e.currentTarget.remove()
        delete window[functionName]    //如果失敗了也要干掉這個函數(shù)

    }
})
jQuery實現(xiàn)

用jQuery就能非常方便的使用

button.addEventListener("click",function(){
    $.ajax({
        url: "http://baidu.com:8002/pay"
        dataType: "JSONP"
        success:function(response){
            console.log(response)
        }
    })
})
JSONP為什么不支持POST請求

因為JSONP是通過動態(tài)創(chuàng)建script實現(xiàn)的

動態(tài)創(chuàng)建script只有GET請求沒有POST請求

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/95290.html

相關(guān)文章

  • 前端相關(guān)大雜燴

    摘要:希望幫助更多的前端愛好者學(xué)習(xí)。前端開發(fā)者指南作者科迪林黎,由前端大師傾情贊助。翻譯最佳實踐譯者張捷滬江前端開發(fā)工程師當(dāng)你問起有關(guān)與時,老司機們首先就會告訴你其實是個沒有網(wǎng)絡(luò)請求功能的庫。 前端基礎(chǔ)面試題(JS部分) 前端基礎(chǔ)面試題(JS部分) 學(xué)習(xí) React.js 比你想象的要簡單 原文地址:Learning React.js is easier than you think 原文作...

    fuyi501 評論0 收藏0
  • AJAX原理和實現(xiàn)方式

    摘要:隨后也跟進抄襲了,取名,并被納入規(guī)范全稱翻譯成中文異步的和技術(shù)的核心是對象簡稱,可以在不刷新頁面頁面也能取得新的數(shù)據(jù)。注意請求和響應(yīng)都不包含信息。 JSONP發(fā)展 了解了JSONP技術(shù)棧后,知道了JSONP是AJAX出現(xiàn)之前后端交互最好的解決方案,但它依然沒解決問題,用JSONP只能發(fā)送GET請求,不能發(fā)其他請求 form表單可以發(fā)GET請求,也可以發(fā)POST請求,POST請求沒有請求...

    missonce 評論0 收藏0
  • 基于Vue.js的音樂播放器(Webapp)

    摘要:概述項目是基于,成品是一個移動端的音樂播放器,來源于的實戰(zhàn)課程。播放器是全局組件,放在下面,通過傳遞數(shù)據(jù),觸發(fā)提交,從而使播放器開始工作。將請求的數(shù)據(jù)格式化后再通過傳遞,組件間共享,實現(xiàn)歌曲的播放切換等。 概述 項目是基于Vue.js,成品是一個移動端的音樂播放器,來源于imooc的實戰(zhàn)課程。自己動手實踐并加以修改拓展。項目的大致流程是Vue-cli構(gòu)建開發(fā)環(huán)境,分析需求,設(shè)計構(gòu)思,規(guī)...

    widuu 評論0 收藏0
  • 如何用vue打造一個移動端音樂播放器

    摘要:寫在前面沒錯,這就是慕課網(wǎng)上的那個音樂播放器,后臺是某音樂播放器的線上接口扒取,雖然這類項目寫的人很多,但不得不說這還是個少有的適合提升的好項目,做這個項目除了想寫一個比較大并且功能復(fù)雜的項目,主要原因是要拿它來應(yīng)對面試,也確實對我的業(yè)務(wù)能 寫在前面 沒錯,這就是慕課網(wǎng)上的那個vue音樂播放器,后臺是某音樂播放器的線上接口扒取,雖然這類項目寫的人很多,但不得不說這還是個少有的適合vu...

    lanffy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<