原生ajax請求&JSONP

_htfire發表於2019-01-07

直接擼程式碼

封裝方法:

        function ajax(options) {
            options = options || {};
            options.type = (options.type || "GET").toUpperCase();
            options.dataType = options.dataType || "json";
            var params = formatParams(options.data);

            //建立 - 非IE6 - 第一步
            if (window.XMLHttpRequest) {
                var xhr = new XMLHttpRequest();
            } else { //IE6及其以下版本瀏覽器
                var xhr = new ActiveXObject('Microsoft.XMLHTTP');
            }

            //連線 和 傳送 - 第二步
            if (options.type == "GET") {
                xhr.open("GET", options.url + "?" + params, true);
                xhr.send(null);
            } else if (options.type == "POST") {
                xhr.open("POST", options.url, true);
                //設定表單提交時的內容型別
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.send(params);
            }

            //接收 - 第三步
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        options.success && options.success(xhr.responseText, xhr.responseXML);
                    } else {
                        options.error && options.error(xhr.status);
                    }
                }
            }
        }
        //格式化引數
        function formatParams(data) {
            var arr = [];
            for (var name in data) {
                arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
            }
            arr.push(("v=" + Math.random()).replace(".", ""));
            console.log(arr);
            return arr.join("&");
        }
複製程式碼

請求例項:

            ajax({
                url: "http://www.xxx.com/app/index",              //請求地址
                type: "get",                       //請求方式
                data: { page: "page" },        //請求引數
                dataType: "json",
                success: function (response, xml) {
                    // 此處放成功後執行的程式碼
                    console.log(JSON.parse(response))
                },
                error: function (status) {
                    // 此處放失敗後執行的程式碼
                }
            });
複製程式碼

JSONP

JSONP的核心是動態新增script標籤來呼叫伺服器提供的js指令碼

function jsonp(options) {
    options = options || {};
    if (!options.url || !options.callback) {
        throw new Error("引數不合法");
    }

    //建立 script 標籤並加入到頁面中
    var callbackName = ('jsonp_' + Math.random()).replace(".", "");
    var oHead = document.getElementsByTagName('head')[0];
    options.data[options.callback] = callbackName;
    var params = formatParams(options.data);
    var oS = document.createElement('script');
    oHead.appendChild(oS);

    //建立jsonp回撥函式
    window[callbackName] = function (json) {
        oHead.removeChild(oS);
        clearTimeout(oS.timer);
        window[callbackName] = null;
        options.success && options.success(json);
    };

    //傳送請求
    oS.src = options.url + '?' + params;

    //超時處理
    if (options.time) {
        oS.timer = setTimeout(function () {
            window[callbackName] = null;
            oHead.removeChild(oS);
            options.fail && options.fail({ message: "超時" });
        }, time);
    }
};

//格式化引數
function formatParams(data) {
    var arr = [];
    for (var name in data) {
        arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[i]));
    }
    return arr.join('&');
}
複製程式碼

ajax與jsonp本質上不是一個東西,ajax的核心是通過XMLHttpRequest物件來獲取非本頁的內容,而jsonp則是通過動態建立script標籤來獲取伺服器端的js指令碼。

ajax與jsonp的本質區別不在於是否跨域,ajax通過伺服器端代理(瀏覽器請求同源伺服器,再由後者請求外部服務)也一樣可以實現跨域,jsonp本身也可以獲取同源的資料。

同源策略

javascript只能訪問與包含他的文件在同一頁面下的內容。

即主機名、協議、埠相同。

//下表給出了相對http://store.company.com/dir/page.html同源檢測的示例: //URL 結果 原因 store.company.com/dir2/other.… 成功
store.company.com/dir/inner/a… 成功
store.company.com/secure.html 失敗 協議不同 store.company.com:81/dir/etc.htm… 失敗 埠不同 news.company.com/dir/other.h… 失敗 主機名不同

相關文章