通過jsonp解決跨域的源碼實現及其特點

一、Jsonp的特點
1、Jsonp是解決跨域的方式之一。
2、Jsonp的核心則是動態添加<script>標籤來調用服務器提供的js腳本,所以兼容性非常好。
3、Jsonp只支持get請求。
4、Jsonp在調用失敗的時候不會返回各種HTTP狀態碼。
5、在請求完畢後通過調用callback的方式回傳結果,將回調方法的權限給了調用方。所以在調用jsonp接口時,需要與被調用方協商好用於callback的參數名字,參數的值爲函數名。例如cb=_jsonp1234。cb爲雙方約定好的參數名,_jsonp1234指定被調用方所要執行的函數名。所以調用方在調用前要保證已方擁有該函數用於接收值。
二、通過Promise封裝Jsonp
/*
* 實現對 Jsonp 的封裝
* url:請求地址
* params:傳遞的參數對象
* jsonp:與服務端協商的用於存放函數名字的參數
* */
export default function jsonp({url = "", params = {}, jsonp = "cb"}) {
    return new Promise((resolve, reject) => {
        // 定義 body 用於接收數據
        let  body = null;
        // 自定義函數的名字
        const cbName = "_jsonp" + Math.random().toString(36).substr(2);
        // 將jsonp放入params
        params[jsonp] =  cbName;
        // 自定義函數,用於接收值
        window[cbName] = function (data) {
            body = data;
        }
        function _handler({type}){
            // 刪除script標籤
            document.body.removeChild(script);
            // 刪除自定義的函數
            delete window[cbName];
            // 加載完畢並得到數據執行resolve
            console.log(1111,body)
            if(type === "load" && !body)  resolve(body);
            // 異常執行 reject
            else if(type === "error") reject("加載失敗");
        }
        // 將對象轉爲urlencoded格式
        const urlencoded = Object.keys(params).map(v => v + "=" + params[v]).join("&");
        // 將地址url與參數進行拼接。
        url += (url.includes("?") ? "&" : "?") + urlencoded;
        // 創建 script 標籤
        const script = document.createElement("script");
        script.src = url;
        // 加載完畢
        script.onload = _handler;
        // 加載異常
        script.onerror = _handler;
        // 指定類型
        script.type = 'text/javascript';
        // 腳本可用,異步執行
        script.async = true;
        // 創建好的script放入body.
        document.body.appendChild(script);
    })
}
四、前端調用
  • 通過百度jsonp的接口進行調用測試:
<script type="module">
    import jsonp from "./jsonp.js";
    // https://www.baidu.com/sugrec?prod=pc&wd=web前端&cb=cb
    (async () => {
        try {
            const res = await jsonp({
                url: "https://www.baidu.com/sugrec",
                params: {
                    prod: "pc",
                    wd: "web前端",// 指定關鍵字
                },
                jsonp: "cb"
            });
            console.log(res);
        } catch (err) {
            console.log(e)
        }
    })();
</script>

—————END—————
分享結束!喜歡本文的朋友們,歡迎關注公衆號 張培躍,收看更多精彩內容,謝過!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章