JavaScript04:擴充進階
一. jsonp
為了解決瀏覽器跨域問題,jQuery提供了jsonp請求
在網頁端如果見到了伺服器返回的資料是:
xxxxxxxxxxdjsfkldasjfkldasjklfjadsklfjasdlkj( { json資料 } )
在Preview裡面可以像看到json一樣去除錯
這就是jsonp,依然是Ajax
jsonp的邏輯是
在傳送請求的時候,帶上一個callback字串(就是json資料外面包裹的字串),該字串自動傳送給伺服器
伺服器返回資料的時候,會帶上該callback字串,在抓包中看到的就是這樣的效果:
在Python中,還原一下該效果
首先, 在flask中,必須接收到前端返回的callback,然後在返回資料的時候,需要用前端返回的callback字串,將資料包裹
@app.route("/process_jsonp", methods=["GET"])
def process_jsonp():
# 獲取回撥字串
cb = request.args.get("cb")
print(cb)
data = {
"name": "alex",
"age": 18
}
import json
# 用回撥字串將真實要返回的資料包裹起來
# 如果不包裹起來。前端ajax中的success將無法獲取到資料
return cb + "("+json.dumps(data)+")"
前端在傳送ajax的時候. 需要指定 dataType為jsonp,以及自由配置回撥函式的引數名
$(function(){
$.ajax({
url: "/process_jsonp",
method:"get",
// 典型:京東
dataType: "jsonp", // 它的執行邏輯是 請求服務上的一個js,然後會自動執行該js,將js函式內的東西,丟給success
jsonp:"cb", // 傳遞給伺服器的時候. 自動帶上cb=xxxxxx 伺服器端接收cb即可
success: function(data){ // 此時data可以直接收取到資料
console.log(data);
}
});
});
抓包效果:
伺服器處理cb時的效果:
抓包中. 看到的伺服器返回的資料
success中接收到的資料效果
- 以後見到這種網站,如何處理?
首先,固定好callback的值。如上述案例. 我們就可以直接給出一個固定的cb值. 如果原網站就是固定的值. 此步驟可以忽略
http://127.0.0.1:5000/process_jsonp?cb=haha&_=1654767783595
然後,得到返回值後,用正則或者字串操作,即可處理
import json
s = 'haha({"name": "alex", "age": 18})' # 得到這樣一個字串. 處理成json很容易的
s = s.strip("haha(").strip(")")
print(s)
dic = json.loads(s)
print(dic)
# 現在請思考. 為什麼要讓你把callback的值固定?
二. axios
由於jquery有嚴重的地獄回撥邏輯,再加上jquery的效能逐年跟不上市場節奏,很多前端工程師採用axios來傳送ajax
相比jQuery,axios更加靈活,且容易使用
更加美麗的是:axios是用promise做的,所以更加貼合大前端的專案需求
<script src="/static/axios.min.js"></script>
<script>
window.onload = function(){
axios.post("/movies", {"page": 10086}).then(function(resp){
console.log(resp.data);
})
}
</script>
// axios 預設傳送json
axios
.post("/movies", {"page": 10086}) // url, json資料
.then(function(resp){ // 回撥函式,處理返回的資料
console.log(resp.data);
})
axios為了更加適應大前端,它預設傳送和接收的資料就是json
所以在瀏覽器抓包時:
直接就是request payload,這對於前端工程師而言,爽爆了。
三. axios攔截器
在前端,能看到有些網站會對每次請求都新增加密資訊,或者每次返回資料的時候,都有解密邏輯
那此時,思考:不可能每次請求都要程式設計師,去手動寫加密邏輯. 例如:
window.onload = function(){
// 一堆加密資料
axios.post("/movies", 加密資料的json資料).then(function(resp){
明文 = 解密(resp.data);
console.log(明文);
})
// 加密資料
axios.post("/movies", {"page": 10086}).then(function(resp){
明文 = 解密(resp.data);
console.log(明文);
})
}
這樣很麻煩,axios想到過類似的問題,它提供了攔截器,一次性處理好這種問題
axios.interceptors.request.use(function(config){ // 攔截所有請求
console.log("我是攔截器. 我可以對資料進行加密");
console.log(config)
return config;
}, function(error){
return Promise.reject(error);
});
axios.interceptors.response.use(function(response){ // 攔截所有響應
console.log("我是響應回來之後攔截器. 我可以對資料進行解密")
return response.data;
}, function(error){
return Promise.reject(error);
});
這樣. 對於業務層的程式碼而言就簡單很多了
window.onload = function(){
// 加密的邏輯攔截器幫我完成了
axios.post("/movies", {"page": 10086}).then(function(data){
// 解密的邏輯攔截器幫我完成了
console.log(data);
})
// 加密的邏輯攔截器幫我完成了
axios.post("/movies", {"page": 10086}).then(function(data){
// 解密的邏輯攔截器幫我完成了
console.log(data);
})
}