一個完整jsonp例項
一個完整jsonp例項
國企車開的就是穩(màn),多了不抱怨了,說事兒。
記上次面試經歷,談到跨域,談到jsonp。因為我們開車穩,所以從不跨域。對於沒有實踐過jsonp的我來說,要是能講明白怎麼回事,就算是挺能忽悠了。但是功力低微啊,結果就是關公門前耍大刀,我覺得網上的理論知識只能讓人懂個大概。這東西不實際操作一下還是差點意思。
伺服器環境
node.js
SPA
html + jquery.js
理論知識點
json:JavaScript Object Notation是一種輕量級的資料交換格式。
優點:輕量級,易讀eval()
轉化為實際的物件,傳輸階段被壓縮,易於機器解析和生成,支援多種語言。
jsonp:Json with Padding是解決跨域問題而提出的一種方案。
原理:由於瀏覽器同源策略的影響,不允許跨域的請求。而script
標籤是一個特例,它的src屬性可以訪問跨域的js,利用這個特性,服務端不再返回json格式的資料,而是返回一段呼叫某個函式的js程式碼。在src中呼叫,達成跨域。
注意
- 1.jsonp只支援GET請求。
- 2.localhost和127.0.0.1也是跨域。
- 3.JSONP中的"P"指什麼?
- 4.一級域名和二級域名也算跨域。
例項解讀
客戶端
通過id="getJsonp"
的按鈕動態建立script標籤,src屬性設定為跨域請求的地址,後接引數,即回撥函式jsonCallback()
。
function createScript(src) { $("<script><\/script>").attr("src",src).appendTo("body") } $("#getJsonp").click(function(){ createScript("http://127.0.0.1:444/somejson?callback=jsonCallback"); });
定義回撥函式該幹嘛,這裡就直接控制檯輸出跨域請求的結果。
function jsonCallback(json) {
console.log(json)
}
頁面所在的服務端
單純一個服務,負責模擬一個web服務。
跨域請求的服務端
對於發出跨域請求的路由,返回的內容為拼接出的一個完整的函式呼叫,這個才是關鍵。
var funcName = url.parse(req.url).query.split('&')[0].split("=")[1] // 取到請求傳入的回撥函式的名稱
var data = {
"name": "MichaelMa",
"age": 26,
"isChild": false
}
switch (pathName){
case "/somejson":
res.writeHead(200, { 'content-type': 'text/plain' })
res.write(funcName + "(" + JSON.stringify(data) + ")") // 在返回內容中拼接出一個完整的函式呼叫,效果就是jsonCallback(data)。這行程式碼是關鍵。
break
default:
res.writeHead(404, { 'content-type': 'text/plain' })
res.write("請求錯誤")
break
}
除錯
啟動兩個服務。一個單純的web服務node serverOrigin.js
,一個跨域請求的目標服務node serverDest.js
。瀏覽器訪問http://localhost:333/jsonpOrigin.html ,開啟開發者工具的console項。點選按鈕頁面上get JSONP按鈕,console內輸出跨域請求的資料。
效果截圖
總結
至此完整的jsonp流程理順了下來,還有jquery ajax封裝的jsonp。原理也是一樣的。希望以後專案中用到時,自己能得心應手。get it!