摘要:同時請求方在本地定義了這個調用函數。如下給調用函數創建一個隨機的函數名為響應網站的域名,為響應網站的端口號定義函數執行結束刪除標簽執行結束刪除函數執行結束刪除標簽執行結束刪除函數響應方根據查詢參數查找到函數名后,回調這個函數,做出響應。
介紹JSONP之前 ,我們先了解一下,頁面數據交互的發展過程。來看下面一個例子。
付款是我們日常中常見的一種金錢交易,用戶在頁面中點擊付款按鈕,網頁提交請求給服務器,服務器收到請求后在數據庫對金額進行扣減,然后將消息返回給頁面,告訴用戶給付款成功。
在jsonp ajax的概念實現之前,以上付款的網頁數據交互過程是怎么實現的呢?
大家都知道form表單有提交post請求功能,我們可以利用form表單,告訴服務器【請求扣款】
頁面代碼如下:用表單提交post請求,請求路徑為/pay
Title 您的賬戶余額是&&&amount&&&
服務器代碼:
當請求的路徑為/pay時,數據庫進行扣減金額一塊錢,然后給頁面返回success,否則告訴頁面請求出錯了。
else if(path === "/pay"){ var amount = fs.readFileSync("./db","utf8"); var newAmount = amount - 1; fs.writeFileSync("./db",newAmount); response.write("success"); response.end(); } else{ response.statusCode = 404 response.setHeader("Content-Type", "text/html;charset=utf-8") response.write("噢噢,好像出錯了呢") response.end() }
效果如下:
這時候大家會發現一個問題,每次頁面返回的success后都要再次刷新頁面才能看到賬戶余額,這樣的體驗并不好,這時候神奇的前端程序員們又想到了一個辦法SRJ方案 SRJ - Server Rendered JavaScript。
這時候就不得不佩服前輩們的‘腦洞’啦。程序員想到script標簽也可以發送請求,因此可以通過動態的創建script標簽來向服務器發送請求,服務器完成操作后,返回結果動態的修該頁面的賬戶金額;同時本地頁面監聽script標簽的onload,onerror事件,來刪除動態創建的script標簽,節省內存。
服務器代碼實現如下:
else if(path === "/pay"){ var amount = fs.readFileSync("./db","utf8"); var newAmount = amount - 1; fs.writeFileSync("./db",newAmount); response.setHeader("Content-Type", "application/javascript") response.statusCode = 200; response.write(`amount.innerText = amount.innerText - 1`); response.end(); } else{ response.statusCode = 404 response.setHeader("Content-Type", "text/html;charset=utf-8") response.write("噢噢,好像出錯了呢") response.end() }
頁面實現:
3.JSONP您的賬戶余額是&&&amount&&&
解決了同一網站的信息交互,那么不同的網站之間(不同的域名),數據要怎么進行交互呢?以上的SRJ也是可以行得通的,只要修改地址為對方網站地址即可。因為script標簽的請求不受域名限制。但是我們發現,如果使用SRJ方案,雙方網站的代碼耦合度太高,為了代碼的解耦,有人提出了JSONP方案:
JSONP(JSON with Padding)是JSON的一種“使用模式”,可用于解決主流瀏覽器的跨域數據訪問的問題。
1.請求方通過動態創建的script標簽的src路徑指向響應方,并且在路徑上添加一個查詢參數(按照約定,參數名為callback),該查詢參數告知響應方應該調用的函數名。同時請求方在本地定義了這個調用函數。如下:
let functionName = "tina"+parseInt(Math.random()*100000,10); //給調用函數創建一個隨機的函數名 script.src = "http://u.com:8002/pay?callback=" + functionName; //u.com為響應網站的域名,8002為響應網站的端口號 window[callback] = function(result){ //定義函數 if(result === "success"){ amount.innerText = amount.innerText - 1; } } script.onload = function(e){ e.currentTarget.remove();//執行結束刪除script標簽 delete window[callback]; //執行結束刪除函數 } script.onerror = function (e) { alert("fail"); e.currentTarget.remove();//執行結束刪除script標簽 delete window[callback];//執行結束刪除函數 } })
2.響應方根據查詢參數查找到函數名后,回調這個函數,做出響應。當回調函數響應的數據("success"P)是json格式時以下的代碼就是JSONP。
response.write(`${query.callback}.call(undefinded,"success")`);
3.完成以上步驟后,請求方得到了響應的數據,就會返回到頁面上。
以上代碼是原生JS的實現,JQuery也封裝了JSONP,代碼如下
//u.com為響應網站的域名,8002為響應網站的端口號 $.ajax({ url: "http://u.com:8002/pay", dataType: "jsonp", success: function( response ) { if(response === "success"){ amount.innerText = amount.innerText - 1 } } }) $.jsonp()
這里值得注意一下JQuery封裝的JSONP雖然起了一個與ajax相近的名字,但是與ajax沒有關系,因為ajax不支持跨域請求。
了解完以上對JSONP的解釋,我們也能很容易明白JSONP為什么不支持POST請求,是因為JSONP是通過動態創建scipt實現的,并且script標簽不支持POST請求。
以上是我個人對JSONP的理解,如有錯誤歡迎指出。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92527.html
摘要:因為同源策略的限制,我們不能在與外部服務器進行通信的時候使用。這個是跨域服務器取數據的接口,參數為回調函數的名字,返回的格式為原理首先在客戶端注冊一個然后把的名字傳給服務器。 一、同源策略 同源策略,它是由Netscape提出的一個著名的安全策略,現在所有的可支持javascript的瀏覽器都會使用這個策略。 為什么需要同源策略,這里舉個例子: 假設現在沒有同源策略,會發生什么事...
摘要:是一種協議,為了解決客戶端請求服務器跨域的問題,但是并非是正式的傳輸協議。結果明明請求回來數據,結果還是報錯。是一種使用數據的方式,返回的不是對象,是包含對象的腳本。 1、什么是JSONP 一般來說位于 server1.example.com 的網頁無法與不是 server1.example.com的服務器溝通,而 HTML 的 元素是一個例外。利用 元素的這個開放策略,網頁可以得到...
摘要:因為有同源策略,而在實際開發中又常常會有跨域的需求,早期開發者為了解決跨域問題而搞出來這樣一個頗為奇怪的東西。安全早期的瀏覽器處于安全層面的考量,制定同源策略,限制了一個源中加載文本或腳本與來自其它源中資源的交互方式。 AJAX、JSON、JSONP 在 WEB 開發中,經常見到諸如 AJAX、JSON、JSONP 這些名詞。三者看起來很像,很多同學尤其是沒有系統了解過前端技術體系的同...