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

資訊專(zhuān)欄INFORMATION COLUMN

JSONP原理

testHs / 775人閱讀

摘要:高級(jí)部分前后端聯(lián)動(dòng)瀏覽器服務(wù)器數(shù)據(jù)庫(kù)是什么文件系統(tǒng)是一種數(shù)據(jù)庫(kù)是一種數(shù)據(jù)庫(kù)也是一個(gè)軟件只要能長(zhǎng)久地存數(shù)據(jù),就是數(shù)據(jù)庫(kù)前后端如何配合接下來(lái)我們用一個(gè)文件充當(dāng)數(shù)據(jù)庫(kù)實(shí)際上數(shù)據(jù)庫(kù)的存儲(chǔ)內(nèi)容本質(zhì)就是一個(gè)帶有結(jié)構(gòu)的文件捋一捋前后端交互的過(guò)程代碼在這里

jsonp

javascript高級(jí)部分:前后端聯(lián)動(dòng),瀏覽器+服務(wù)器

1數(shù)據(jù)庫(kù)是什么

文件系統(tǒng)是一種數(shù)據(jù)庫(kù)
MySQL 是一種數(shù)據(jù)庫(kù),也是一個(gè)軟件
只要能長(zhǎng)久地存數(shù)據(jù),就是數(shù)據(jù)庫(kù)

2前后端如何配合?

接下來(lái)我們用一個(gè)文件充當(dāng)數(shù)據(jù)庫(kù)(實(shí)際上數(shù)據(jù)庫(kù)的存儲(chǔ)內(nèi)容本質(zhì)就是一個(gè)帶有結(jié)構(gòu)的文件),捋一捋前后端交互的過(guò)程.

代碼在這里
幾次代碼的變更在歷史commit里

首先寫(xiě)一個(gè)首頁(yè)

首頁(yè)

我的余額為&&&amount&&&

再寫(xiě)服務(wù)器的代碼

var http = require("http")
var fs = require("fs")
var url = require("url")

var port = process.env.PORT || 8888;

var server = http.createServer(function (request, response) {

    var temp = url.parse(request.url, true)
    var path = temp.pathname
    var query = temp.query
    var method = request.method

    //從這里開(kāi)始看,上面不要看

    if (path === "/") {  // 如果用戶請(qǐng)求的是 / 路徑
        var string = fs.readFileSync("./index.html")  // 就讀取 index.html 的內(nèi)容
        var amount = fs.readFileSync("./db","utf-8")//****從數(shù)據(jù)庫(kù)(db文件)同步讀取數(shù)據(jù),放到amount變量里
        string = string.toString().replace("&&&amount&&&",amount)//將后臺(tái)的amount替換為前臺(tái)的占位符&&&amount&&&

        response.setHeader("Content-Type", "text/html;charset=utf-8")  // 設(shè)置響應(yīng)頭 Content-Type
        response.write(string)   // 設(shè)置響應(yīng)消息體
        response.end();
    } else if (path === "/style.css") {   // 如果用戶請(qǐng)求的是 /style.css 路徑
        var string = fs.readFileSync("./style.css")
        response.setHeader("Content-Type", "text/css")
        response.write(string)
        response.end()
    } else if (path === "/main.js") {  // 如果用戶請(qǐng)求的是 /main.js 路徑
        var string = fs.readFileSync("./main.js")
        response.setHeader("Content-Type", "application/javascript")
        response.write(string)
        response.end()
    } else if(path === "/pay" && method.toUpperCase() === "POST"){//如果請(qǐng)求的路徑是pay且方法為post
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;
        fs.writeFileSync("./db",newAmount);
        response.write("success")
        response.end()
    }else {  // 如果上面都不是用戶請(qǐng)求的路徑
        response.statusCode = 404
        response.setHeader("Content-Type", "text/html;charset=utf-8")  // 設(shè)置響應(yīng)頭 Content-Type
        response.write("找不到對(duì)應(yīng)的路徑,你需要自行修改 index.js")
        response.end()
    }

    // 代碼結(jié)束,下面不要看
    console.log(method + " " + request.url)
})

server.listen(port)
console.log("監(jiān)聽(tīng) " + port + " 成功,請(qǐng)用在空中轉(zhuǎn)體720度然后用電飯煲打開(kāi) http://localhost:" + port)

最后在創(chuàng)建一個(gè)名為db的文本文件充當(dāng)數(shù)據(jù)庫(kù)

接著我們開(kāi)啟服務(wù)器
node index.js 8888


接著在瀏覽器中輸入地址http://localhost:8888
當(dāng)用戶打開(kāi)瀏覽器輸入ip地址,就會(huì)向后臺(tái)發(fā)送請(qǐng)求,服務(wù)器發(fā)現(xiàn)地址是/之后執(zhí)行if elsepath==="/"分支,執(zhí)行下面的代碼:

if (path === "/") {  // 如果用戶請(qǐng)求的是 / 路徑
        var string = fs.readFileSync("./index.html")  // 就讀取 index.html 的內(nèi)容
        var amount = fs.readFileSync("./db","utf-8")//****從數(shù)據(jù)庫(kù)(db文件)同步讀取數(shù)據(jù),放到amount變量里
        string = string.toString().replace("&&&amount&&&",amount)//將后臺(tái)的amount替換為前臺(tái)的占位符&&&amount&&&

        response.setHeader("Content-Type", "text/html;charset=utf-8")  // 設(shè)置響應(yīng)頭 Content-Type
        response.write(string)   // 設(shè)置響應(yīng)消息體
        response.end();
    } 

接著點(diǎn)擊提交按鈕,就會(huì)向后臺(tái)發(fā)起post請(qǐng)求,請(qǐng)求路徑為/pay,于是進(jìn)入path === "/pay"分支,執(zhí)行下面的代碼,使數(shù)據(jù)庫(kù)(這里數(shù)據(jù)庫(kù)用一個(gè)文本文件代替)中的金額減一

else if(path === "/pay" && method.toUpperCase() === "POST"){//如果請(qǐng)求的路徑是pay且方法為post
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;
        fs.writeFileSync("./db",newAmount);
        response.write("success")
        response.end()
    }

然后會(huì)發(fā)現(xiàn)/pay頁(yè)面返回了success

返回剛才的首頁(yè),刷新后,會(huì)發(fā)現(xiàn)金額減少了1.

也可以模擬后臺(tái)修改數(shù)據(jù)庫(kù)成功或失敗

 else if(path === "/pay" && method.toUpperCase() === "POST"){//如果請(qǐng)求的路徑是pay且方法為post
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;
        if(Math.random()>0.5){//模擬成功或失敗
            fs.writeFileSync("./db",newAmount);
            response.write("success")
        }else{
            response.write("fail")
        }
        response.end()
    }
3 優(yōu)化體驗(yàn):用image和script發(fā)送請(qǐng)求

但是剛才那樣體驗(yàn)非常不好,因?yàn)橐祷?要刷新.在2005年以前,網(wǎng)頁(yè)的前后端交互都是這樣.但現(xiàn)在是8012年了,我們需要優(yōu)化一下用戶體驗(yàn)

不光form表單可以發(fā)送請(qǐng)求,a標(biāo)簽(需要點(diǎn)擊),link標(biāo)簽,script,圖片,都可以發(fā)送請(qǐng)求

3.1用image發(fā)送請(qǐng)求

那我們先試試用img發(fā)送一個(gè)請(qǐng)求
當(dāng)瀏覽器發(fā)現(xiàn)html里面有一個(gè)img時(shí),會(huì)自動(dòng)發(fā)送請(qǐng)求,請(qǐng)求路徑就是img的src.但是有一個(gè)缺點(diǎn).發(fā)送的請(qǐng)求只能是get,沒(méi)辦法改成post.
使用img.onload和img.onerror方法判斷請(qǐng)求是成功還是失敗,具體操作看下方代碼

復(fù)習(xí)一下返回的狀態(tài)碼:
2開(kāi)頭:成功
3開(kāi)頭:重定向
4開(kāi)頭:客戶端錯(cuò)誤
5開(kāi)頭:服務(wù)器錯(cuò)誤

修改首頁(yè)

首頁(yè)

我的余額為&&&amount&&&

修改/pay路徑的響應(yīng)

else if(path === "/pay"){//如果請(qǐng)求的路徑是pay,接受圖片的請(qǐng)求
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;
        if(Math.random()>0.5){//模擬成功或失敗
            fs.writeFileSync("./db",newAmount);//成功了就把數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)
            response.setHeader("Content-Type","image/jpg")//設(shè)置返回文件類(lèi)型為jpg
            response.statusCode = 200;//返回碼為200,說(shuō)明成功
            response.write(fs.readFileSync("./dog.jpg"))//必須返回一個(gè)真的圖片,不然瀏覽器還是會(huì)認(rèn)為是失敗
        }else{
            response.statusCode = 400;//否則返回碼為400,說(shuō)明失敗
            response.write("fail")
        }
        response.end()
    }

然后開(kāi)啟服務(wù)器,瀏覽器輸入地址
點(diǎn)擊付錢(qián),成功,并刷新

付錢(qián)失敗時(shí),彈框后瀏覽器就不刷新了:

也可局部刷新

img.onload = function(){//如果圖片請(qǐng)求成功(返回碼以2開(kāi)頭)
            alert("付錢(qián)成功")
                        amount.innerText = amount.innerText-1;//局部刷新/因?yàn)橐呀?jīng)知道數(shù)據(jù)庫(kù)修改成功,所以無(wú)需再進(jìn)行刷新,直接修改數(shù)值即可

        }

還有一個(gè)需要注意的點(diǎn)
在下面這段代碼中

 response.setHeader("Content-Type","image/jpg")//設(shè)置返回文件類(lèi)型為jpg,
            response.statusCode = 200;//返回碼為200,說(shuō)明成功
            response.write(fs.readFileSync("./dog.jpg"))//必須返回一個(gè)真的圖片,不然瀏覽器還是會(huì)認(rèn)為是失敗

看看回復(fù)的響應(yīng)
response.write(fs.readFileSync("./dog.jpg"))這句代碼中fs.readFileSync("./dog.jpg")參數(shù)里只有路徑,沒(méi)有加別的,那么讀出來(lái)的數(shù)據(jù)類(lèi)型為2進(jìn)制數(shù)據(jù),然后"Content-Type","image/jpg"這句代碼表示以jpg圖片的形式讀取這段二進(jìn)制代碼.

復(fù)習(xí)一下響應(yīng)的四個(gè)部分:

1 協(xié)議/版本號(hào) 狀態(tài)碼 狀態(tài)解釋
2 Key1: value1
2 Key2: value2
2 Content-Length: 17931
2 Content-Type: text/html
3
4 響應(yīng)的內(nèi)容

response.write(fs.readFileSync("./dog.jpg"))這句代碼就是響應(yīng)的第四部分,即響應(yīng)的內(nèi)容

3.2用script發(fā)送請(qǐng)求

那么我們也可以用script動(dòng)態(tài)的發(fā)送請(qǐng)求.原理和img類(lèi)似,但是必須得把script標(biāo)簽加入到body里面,才會(huì)發(fā)送請(qǐng)求,而img標(biāo)簽只要?jiǎng)?chuàng)建,就會(huì)發(fā)送請(qǐng)求.
接下來(lái)看代碼
首頁(yè)的發(fā)送請(qǐng)求代碼

服務(wù)器端的代碼:

else if(path === "/pay"){//如果請(qǐng)求的路徑是pay,接受script的請(qǐng)求
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;

        if(Math.random()>0.5){//模擬成功或失敗
            fs.writeFileSync("./db",newAmount);//成功了就把數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)
            
            response.setHeader("Content-Type","applacation/javascript")//設(shè)置返回文件類(lèi)型為javascript
            response.statusCode = 200;//返回碼為200,說(shuō)明成功
            response.write("alert("我是創(chuàng)建的script請(qǐng)求里面響應(yīng)的內(nèi)容")")//響應(yīng)內(nèi)容為創(chuàng)建的script標(biāo)簽里面的內(nèi)容
        }else{
            response.statusCode = 400;//否則返回碼為400,說(shuō)明失敗
            response.write("fail")
        }
        response.end()
    }

當(dāng)我點(diǎn)擊打錢(qián)的時(shí)候,他會(huì)動(dòng)態(tài)的創(chuàng)建一個(gè)script,這個(gè)script會(huì)根據(jù)src發(fā)起請(qǐng)求

進(jìn)入失敗分支:

成功:
先執(zhí)行請(qǐng)求使用的script里面的語(yǔ)句

每次請(qǐng)求就會(huì)創(chuàng)建一個(gè)新的script標(biāo)簽,如果響應(yīng)成功了,就執(zhí)行響應(yīng)里面的javascript語(yǔ)句,這個(gè)script里面的語(yǔ)句就是返回的響應(yīng)的第四部分的內(nèi)容,執(zhí)行完之后才會(huì)觸發(fā)onload事件

3.2.1優(yōu)化用戶體驗(yàn)

那么既然請(qǐng)求返回的響應(yīng)可以執(zhí)行,我們就不需要寫(xiě)onload了,直接把onload里面的代碼寫(xiě)在響應(yīng)的第四部分不就可以了?沒(méi)錯(cuò)

接來(lái)下修改一下代碼,刪掉onload代碼,將onload里面的代碼寫(xiě)在服務(wù)器端.將前臺(tái)請(qǐng)求成功要做的事情交給后臺(tái)來(lái)做.

btn.onclick = function(){
        let script = document.createElement("script");
        script.src = "/pay";

        document.body.appendChild(script);//這句話一定要加上,這是與使用圖片請(qǐng)求不一樣的地方

        //刪除onload代碼,交給后臺(tái)來(lái)做
        script.onerror = function(){//返回碼是4開(kāi)頭
            alert("付錢(qián)失敗");
        }
    }

后臺(tái)只需要將金額數(shù)量減1即可,不需要刷新,增加用戶體驗(yàn)

 else if(path === "/pay"){//如果請(qǐng)求的路徑是pay,接受script的請(qǐng)求
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;

        if(Math.random()>0.5){//模擬成功或失敗
            fs.writeFileSync("./db",newAmount);//成功了就把數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)

            response.setHeader("Content-Type","applacation/javascript")//設(shè)置返回文件類(lèi)型為javascript
            response.statusCode = 200;//返回碼為200,說(shuō)明成功
            response.write("amount.innerText = amount.innerText-1")//響應(yīng)內(nèi)容為創(chuàng)建的script標(biāo)簽里面的內(nèi)容,返回后會(huì)立即執(zhí)行*********
        }else{
            response.statusCode = 400;//否則返回碼為400,說(shuō)明失敗
            response.write("fail")
        }
        response.end()
    }else

最后在做一件事情

因?yàn)槊看尾还艹晒κ?都會(huì)創(chuàng)建一個(gè)script標(biāo)簽,那么可否在請(qǐng)求結(jié)束后,將標(biāo)簽刪除?
可以.
修改前臺(tái)onload和onerror代碼即可,不管請(qǐng)求成功失敗,都移除script標(biāo)簽

script.onload = function(e){
            e.currentTarget.remove();//添加移除代碼
        }
        script.onerror = function(e){
            e.currentTarget.remove();
        }
3.2.2總結(jié) SRJ(server rrendered javascript--服務(wù)器返回的javascript)

以上方法就叫做SRJ,服務(wù)器返回的javascript,即不是在前臺(tái)寫(xiě)的javascript
這是在ajax出現(xiàn)之前,后端程序員想出來(lái)的前后臺(tái)無(wú)刷新,局部更新頁(yè)面內(nèi)容的交互方法

4 請(qǐng)求另個(gè)一網(wǎng)站的script

script請(qǐng)求的內(nèi)容不受域名限制.當(dāng)前網(wǎng)站的可以請(qǐng)求其他網(wǎng)站的js代碼,例如jquery

可以引入jquery

所以剛才的SRJ很危險(xiǎn),假如只用了get方法,那么像付錢(qián)這種操作很容易被偽裝成功,導(dǎo)致別人的惡意攻擊
例如我進(jìn)入一個(gè)釣魚(yú)網(wǎng)站
那個(gè)網(wǎng)站直接請(qǐng)求
script.src = "http://alipay.com/pay?usname=mataotao&amount=100000"
這樣只要進(jìn)入網(wǎng)站執(zhí)行這個(gè)請(qǐng)求,豈不是可以隨意給自己的賬戶打錢(qián)?
所以只用get不安全.
所以很多危險(xiǎn)操作都得用POST請(qǐng)求,例如打錢(qián)必須驗(yàn)證用戶,做各種支付相關(guān)的安全防范,手機(jī)驗(yàn)證碼之類(lèi)的.

下面我們模仿一下不同的網(wǎng)站請(qǐng)求對(duì)方的后臺(tái)的過(guò)程
首先修改一下本地的hosts文件,將兩個(gè)域名都指向127.0.0.1,假裝成兩個(gè)不同的網(wǎng)站

hosts文件相當(dāng)于一個(gè)個(gè)人的DNS,當(dāng)你訪問(wèn)某個(gè)域名時(shí),是先通過(guò)hosts進(jìn)行解析的,沒(méi)有找到才進(jìn)一步通過(guò)外網(wǎng)DNS服務(wù)器進(jìn)行解析。

如果是windows系統(tǒng):
windows系統(tǒng)hosts文件位置及操作
如果是linux或者Unix
地址為/etc/hosts


添加代碼,那么如果我在本地訪問(wèn)mataotao.com和jack.com,他首先會(huì)進(jìn)127.0.0.1,而不是去外網(wǎng)解析dns
這樣我們就假裝成為了兩個(gè)網(wǎng)站,實(shí)際上兩個(gè)網(wǎng)站的內(nèi)容是一樣的,知識(shí)用來(lái)做實(shí)驗(yàn)

然后開(kāi)兩個(gè)服務(wù)器,使用兩個(gè)不同的端口來(lái)監(jiān)聽(tīng)(模擬兩個(gè)不同的網(wǎng)站都開(kāi)啟了服務(wù)器,都在監(jiān)聽(tīng))
監(jiān)聽(tīng)8001

監(jiān)聽(tīng)8002

這樣我們?cè)诘刂窓谳斎?b>mataotao.com:8001就進(jìn)入了第一個(gè)網(wǎng)站,在地址欄輸入jack.com:8002
就進(jìn)入了第二個(gè)網(wǎng)站.

這樣兩個(gè)個(gè)網(wǎng)站都可以接受請(qǐng)求,都可以訪問(wèn),只不過(guò)內(nèi)容一樣而已
那么接下來(lái)我們來(lái)模仿不同網(wǎng)站之間的請(qǐng)求互動(dòng)

修改前端SRJ請(qǐng)求代碼的請(qǐng)求路徑,改為script.src = "http://jack.com:8002/pay";
那么我們打開(kāi)mataotao.com:8001就進(jìn)入了第一個(gè)網(wǎng)站,點(diǎn)擊按鈕后,意思就是請(qǐng)求http://jack.com:8002/pay這個(gè)第二個(gè)網(wǎng)站的地址.我們來(lái)試一試


結(jié)果如圖所示

這是成功的時(shí)候

可以看到,兩個(gè)完全不同的網(wǎng)站,他們兩個(gè)是可以互相調(diào)script的

這時(shí)候的意思是:我是用第一個(gè)網(wǎng)站(mataotao.com)打開(kāi)了第二個(gè)網(wǎng)站(jack.com)的付錢(qián)功能!
(由于我為了演示,這兩個(gè)網(wǎng)站用了同樣的代碼,同一個(gè)數(shù)據(jù)庫(kù),我們假設(shè)第一個(gè)網(wǎng)站he第二個(gè)網(wǎng)站代碼不同)

5 jsonp

這時(shí)候出現(xiàn)一個(gè)問(wèn)題:
jack.com的后端程序員需要對(duì)mataotao.com的頁(yè)面細(xì)節(jié)了解的很清楚.
這樣的缺點(diǎn)是后臺(tái)對(duì)前臺(tái)需要了解得太深入了.比如說(shuō)你是node或者php騰訊后端程序員,可是我竟然還要對(duì)阿里巴巴網(wǎng)站的一個(gè)按鈕的一個(gè)細(xì)節(jié)非常了解.耦合度太高,前后端彼此之間關(guān)系太緊密了.如果后端程序員對(duì)頁(yè)面細(xì)節(jié)不了解,代碼就寫(xiě)不下去了.這樣對(duì)前后端分離不友好

5.1解決前后端耦合度太高的問(wèn)題

解耦(解決耦合問(wèn)題)
解決方法:

后臺(tái)程序員:我只把我后臺(tái)應(yīng)該改的數(shù)據(jù)庫(kù),然后我寫(xiě)一個(gè)callback函數(shù),將成功和失敗的狀態(tài)傳遞給前臺(tái).這個(gè)函數(shù)就是我后端程序員做完這些事情成功之后要前端程序員去做的事情.然后執(zhí)行這個(gè)函數(shù),這個(gè)函數(shù)的內(nèi)容交給前端去寫(xiě).

前端程序員:我不管后端如何修改數(shù)據(jù)庫(kù),我事先寫(xiě)好成功和失敗的函數(shù),成功了就返回給我一個(gè)成功的提示,然后我根據(jù)提示執(zhí)行成功的函數(shù),如果給我的提示是失敗,就執(zhí)行失敗的函數(shù).
接下來(lái)寫(xiě)代碼理解:
修改服務(wù)器端的代碼:

response.write(`${query.callbackName}.call(undefined,"success")`)//先獲取查詢字符串里的callbackName即從前臺(tái)傳過(guò)來(lái)的回調(diào)函數(shù)的函數(shù)名,然后再執(zhí)行他,并把函數(shù)的參數(shù)定為success

添加前臺(tái)index.html的代碼

添加的這幾句代碼的解釋:
首先
script.src = "http://jack.com:8002/pay?callbackName=xxx";
在請(qǐng)求時(shí)帶上查詢參數(shù),指定callbackName為xxx,以便給后臺(tái)程序員調(diào)用
接著

response.write(`${query.callbackName}.call(undefined,"success")`)

后臺(tái)程序員獲得前太程序員的查詢參數(shù),并執(zhí)行名為查詢參數(shù)的函數(shù)xxx

執(zhí)行xxx,并且將相應(yīng)的內(nèi)容作為回調(diào)函數(shù)的第一個(gè)參數(shù)傳回去,這個(gè)參數(shù)為字符串"success"

window.xxx = function(result){
        alert("我是前端程序員寫(xiě)的函數(shù),經(jīng)過(guò)后端程序員調(diào)用才執(zhí)行")
        alert(`后端返回回來(lái)的函數(shù)參數(shù)是:${result}`)
    }

執(zhí)行結(jié)果:


也可以根據(jù)后臺(tái)傳過(guò)來(lái)的參數(shù),修改前臺(tái)的邏輯

window.xxx = function(result){
        if(result === "success"){
            amount.innerText = amount.innerText - 1;
        }
    }

那么如果我們返回的參數(shù)不是字符串,而是對(duì)象呢?
這也是可以的,例如我們修改一下代碼

else if(path === "/pay"){//如果請(qǐng)求的路徑是pay,接受script的請(qǐng)求
        var amount = fs.readFileSync("./db","utf-8")
        var newAmount = amount-1;

        if(Math.random()>0.5){//模擬成功或失敗
            fs.writeFileSync("./db",newAmount);//成功了就把數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)

            response.setHeader("Content-Type","applacation/javascript")//設(shè)置返回文件類(lèi)型為javascript
            response.statusCode = 200;//返回碼為200,說(shuō)明成功
            response.write(`${query.callbackName}.call(undefined,{
                "success":true,
                "left":${newAmount}
            })`)//把函數(shù)的參數(shù)定為一個(gè)對(duì)象
        }else{
         
            response.statusCode = 400;//否則返回碼為400,說(shuō)明失敗
            response.write("fail")
        }
        response.end()
    }

前端:

    window.xxx = function(result){
        if(result.success === true){
            amount.innerText = amount.innerText - 1;
        }
    }
5.2jsonp的含義和理解

我請(qǐng)求一個(gè)script,script調(diào)用一個(gè)函數(shù)的同時(shí),把第一個(gè)參數(shù)設(shè)置為要返回的數(shù)據(jù),不管這個(gè)數(shù)據(jù)是對(duì)象還是字符串.然后人們把這種調(diào)用script并返回字符串或者對(duì)象的使用方法叫做是jsonp,這就是jsonp!.只是名字比較奇怪,其實(shí)真名的名字應(yīng)該是:動(dòng)態(tài)標(biāo)簽跨域請(qǐng)求!即利用動(dòng)態(tài)標(biāo)簽進(jìn)行跨域請(qǐng)求的技術(shù)

這種方法的好處是可以解決跨域的問(wèn)題.例如剛才的例子,兩個(gè)網(wǎng)站如果域名不一樣,那么第一個(gè)網(wǎng)址的前臺(tái)和另一個(gè)網(wǎng)址后臺(tái)的服務(wù)器無(wú)法進(jìn)行數(shù)據(jù)交換(由于瀏覽器的同源策略).但是使用script標(biāo)簽就可以避免這個(gè)問(wèn)題.利用script請(qǐng)求,可以請(qǐng)求道第二個(gè)網(wǎng)站的json或字符串?dāng)?shù)據(jù),這種方法就叫做jsonp

JSONP(JSON with Padding)是JSON的一種“使用模式”,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。由于同源策略,一般來(lái)說(shuō)位于 server1.example.com 的網(wǎng)頁(yè)無(wú)法與不是 server1.example.com的服務(wù)器溝通,而 HTML 的
 response.write(`${query.callback}.call(undefined,{
                "success":true,
                "left":${newAmount}
            })`)


1隨機(jī)生成的查詢字符串
2返回的根據(jù)隨機(jī)生成的函數(shù)名的數(shù)據(jù)

6 使用jQuery中的jsonp

jQuery使用jsonp非常簡(jiǎn)單

只要這樣修改前臺(tái)的代碼.后臺(tái)不用改 url不需要寫(xiě)callback查詢參數(shù),因?yàn)閖Query會(huì)自動(dòng)給你生成

btn.onclick = function () {

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

需要注意的一點(diǎn)是,jsonp不是ajax中的一種.不要背jquery誤導(dǎo)

7 面試題:jsonp為什么不能用post請(qǐng)求

答:

jsonp是通過(guò)動(dòng)態(tài)創(chuàng)建script實(shí)現(xiàn)的

動(dòng)態(tài)創(chuàng)建script的時(shí)候只能用get,沒(méi)有辦法用post

6 什么json

JSON 語(yǔ)法

6.1JSON 語(yǔ)法規(guī)則

在 JS 語(yǔ)言中,一切都是對(duì)象。因此,任何支持的類(lèi)型都可以通過(guò) JSON 來(lái)表示,例如字符串、數(shù)字、對(duì)象、數(shù)組等。但是對(duì)象和數(shù)組是比較特殊且常用的兩種類(lèi)型:

對(duì)象表示為鍵值對(duì)

數(shù)據(jù)由逗號(hào)分隔

花括號(hào)保存對(duì)象

方括號(hào)保存數(shù)組

6.2JSON 鍵/值對(duì)

JSON 鍵值對(duì)是用來(lái)保存 JS 對(duì)象的一種方式,和 JS 對(duì)象的寫(xiě)法也大同小異,鍵/值對(duì)組合中的鍵名寫(xiě)在前面并用雙引號(hào) "" 包裹,使用冒號(hào) : 分隔,然后緊接著值:

{"firstName": "Json"}

這很容易理解,等價(jià)于這條 JavaScript 語(yǔ)句:

{firstName : "Json"}
6.3 JSON 與 JS 對(duì)象的關(guān)系

很多人搞不清楚 JSON 和 Js 對(duì)象的關(guān)系,甚至連誰(shuí)是誰(shuí)都不清楚。其實(shí),可以這么理解:
JSON 是 JS 對(duì)象的字符串表示法,它使用文本表示一個(gè) JS 對(duì)象的信息,本質(zhì)是一個(gè)字符串。

var obj = {a: "Hello", b: "World"};
//這是一個(gè)對(duì)象,注意鍵名也是可以使用引號(hào)包裹的
var json = "{"a": "Hello", "b": "World"}"; //這是一個(gè) JSON 字符串,本質(zhì)是一個(gè)字符串
6.4JSON 和 JS 對(duì)象互轉(zhuǎn)

要實(shí)現(xiàn)從對(duì)象轉(zhuǎn)換為 JSON 字符串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: "Hello", b: "World"}); //結(jié)果是 "{"a": "Hello", "b": "World"}"

要實(shí)現(xiàn)從 JSON 轉(zhuǎn)換為對(duì)象,使用 JSON.parse() 方法:

var obj = JSON.parse("{"a": "Hello", "b": "World"}"); //結(jié)果是 {a: "Hello", b: "World"}

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

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

相關(guān)文章

  • JSONP原理及實(shí)現(xiàn)跨域方式

    摘要:同源策略限制了我們無(wú)法通過(guò)原生的對(duì)象獲取到數(shù)據(jù)。的原理其實(shí)不復(fù)雜瀏覽器的同源策略把跨域請(qǐng)求都禁止了的標(biāo)簽是例外,可以突破同源策略從其他來(lái)源獲取數(shù)據(jù)由上可得,我們可以通過(guò)標(biāo)簽引入文件,然后通過(guò)一系列操作獲取數(shù)據(jù)。上面三點(diǎn)便是實(shí)現(xiàn)跨域的原理。 今天做頁(yè)面時(shí),后臺(tái)給了個(gè)接口:https://a.a.com/a/a.json,我頁(yè)面的上線地址是:http://b.b.com。顯而易見(jiàn),因?yàn)闉g覽...

    The question 評(píng)論0 收藏0
  • JSONP原理及JQUERY JSONP的使用

    摘要:同源策略在中有一個(gè)很重要的安全性限制,被稱為同源策略。然而,當(dāng)進(jìn)行一些比較深入的前端編程的時(shí)候,不可避免地需要進(jìn)行跨域操作,這時(shí)候同源策略就顯得過(guò)于苛刻。 JSONP原理 JSON和JSONP   JSON(JavaScript Object Notation)是一種輕量級(jí)的數(shù)據(jù)交換格式。對(duì)于JSON大家應(yīng)該是很了解了吧,不是很清楚的朋友可以去json.org上了解下,簡(jiǎn)單易懂。   ...

    suosuopuo 評(píng)論0 收藏0
  • JSONP原理剖析

    摘要:運(yùn)行一下頁(yè)面,成功彈出提示窗口,的執(zhí)行全過(guò)程順利完成到這里為止的話,相信你已經(jīng)能夠理解的客戶端實(shí)現(xiàn)原理了吧剩下的就是如何把代碼封裝一下,以便于與用戶界面交互,從而實(shí)現(xiàn)多次和重復(fù)調(diào)用。 先說(shuō)說(shuō)JSONP是怎么產(chǎn)生的: 其實(shí)網(wǎng)上關(guān)于JSONP的講解有很多,但卻千篇一律,而且云里霧里,對(duì)于很多剛接觸的人來(lái)講理解起來(lái)有些困難,小可不才,試著用自己的方式來(lái)闡釋一下這個(gè)問(wèn)題,看看是否有幫助。 1、...

    DangoSky 評(píng)論0 收藏0
  • jsonp原理與實(shí)現(xiàn)

    摘要:概述是一種跨域通信的手段,它的原理其實(shí)很簡(jiǎn)單首先是利用標(biāo)簽的屬性來(lái)實(shí)現(xiàn)跨域??煽康膶?shí)現(xiàn)添加回調(diào)函數(shù)拼接傳遞的是一個(gè)匿名的回調(diào)函數(shù),要執(zhí)行的話,暴露為一個(gè)全局方法出錯(cuò)處理使用示例來(lái)源個(gè)人博客 1. 概述 jsonp是一種跨域通信的手段,它的原理其實(shí)很簡(jiǎn)單: 首先是利用script標(biāo)簽的src屬性來(lái)實(shí)現(xiàn)跨域。 通過(guò)將前端方法作為參數(shù)傳遞到服務(wù)器端,然后由服務(wù)器端注入?yún)?shù)之后再返回,實(shí)現(xiàn)服...

    SillyMonkey 評(píng)論0 收藏0
  • jsonp原理介紹及Promise封裝

    摘要:什么叫是填充式或參數(shù)式的簡(jiǎn)寫(xiě),是通過(guò)請(qǐng)求跨域接口,獲取數(shù)據(jù)的新實(shí)現(xiàn)方式的實(shí)現(xiàn)原理動(dòng)態(tài)創(chuàng)建標(biāo)簽,因?yàn)闃?biāo)簽是沒(méi)有同源策略限制,可以跨域的。具體看接下來(lái)的實(shí)現(xiàn)這個(gè)是庫(kù)的具體實(shí)現(xiàn),建議下載來(lái)研究一下,最好自己動(dòng)手寫(xiě)一遍。 什么叫jsonp? jsonp是json with padding(填充式j(luò)son或參數(shù)式j(luò)son)的簡(jiǎn)寫(xiě),是通過(guò)ajax請(qǐng)求跨域接口,獲取數(shù)據(jù)的新實(shí)現(xiàn)方式 jsonp的實(shí)現(xiàn)...

    ninefive 評(píng)論0 收藏0
  • 關(guān)于javascript跨域及JSONP原理與應(yīng)用

    摘要:因?yàn)橥床呗缘南拗疲覀儾荒茉谂c外部服務(wù)器進(jìn)行通信的時(shí)候使用。這個(gè)是跨域服務(wù)器取數(shù)據(jù)的接口,參數(shù)為回調(diào)函數(shù)的名字,返回的格式為原理首先在客戶端注冊(cè)一個(gè)然后把的名字傳給服務(wù)器。 一、同源策略 同源策略,它是由Netscape提出的一個(gè)著名的安全策略,現(xiàn)在所有的可支持javascript的瀏覽器都會(huì)使用這個(gè)策略。 為什么需要同源策略,這里舉個(gè)例子: 假設(shè)現(xiàn)在沒(méi)有同源策略,會(huì)發(fā)生什么事...

    CoderBear 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<