04--JS04--進階

Edmond辉仔發表於2024-05-20

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