jsonp封裝

 

/*
1. 每一個jsonp請求惟一,防止緩存,每一個請求存儲內容以下
    {
        callback: function(){},
        scriptNode: [domNode]
        timer: [定時器]
    }
2. src的參數須要編碼
3. 請求超時,拋出錯誤
4. 使用說明,使用方式相似JQuey的ajax方式,例: jsonp({
      url:[string],
      data:[obj],
      callback:[function],
      fail: [function],
      timeout: [number]
})
*/

function jsonp(opts) {
    if (!opts || !opts.url) {
        return;
    }
    // 初始化參數
    var options = {
        url: opts.url,
        data: opts.data ? opts.data : null,
        callback: opts.callback ? opts.callback : null,
        fail: opts.fail ? opts.fail : null,
        timeout: opts.timeout ? opts.timeout : 3000
    }
    var helper = {
        joinURL: function(url, data) {
            if (!url || !data) {
                return;
            }
            for (var i in data) {
                if (data.hasOwnProperty(i)) {
                    if (url.indexOf("?") >= 0) {
                        url += "&";
                    } else {
                        url += "?";
                    }
                    url += i + "=" + data[i];
                }
            }
            return url;
        },
        encodeURL: function(url) {
            var param = url.split("?")[1];
            var url = url.split("?")[0];
            var params = param.split("&");
            var parLen = params.length;

            for (var i = 0; i < parLen; i++) {
                var paItem = params[i].split("=");
                url += url.indexOf("?") >= 0 ? "&" : "?";
                url += encodeURIComponent(paItem[0]) + "=" + encodeURIComponent(paItem[1]);
            }
            return url;
        },
    };

    // new Date().getTime()不夠精確,加上count計數,確保惟一,也能夠使用隨機函數,但我認爲這樣更簡單。
    if (window["count"]) {
        window["count"]++;
    } else {
        window["count"] = 1;
    }

    // requestId 惟一jsonp請求
    var requestId = "jsonp" + new Date().getTime() + window['count'];

    var head = document.getElementsByTagName("head")[0];
    var script = null;
    window[requestId] = {};

    // 請求值拼接到url

    if (options.data) {
        options.url = helper.joinURL(options.url, options.data);
    }

    //建立script結點
    script = document.createElement("script");
    if (options.url.indexOf("?") >= 0) {
        script.src = helper.encodeURL(options.url + "&callback=" + requestId + ".callback");
    } else {
        script.src = helper.encodeURL(options.url + "?callback=" + requestId + ".callback");
    }
    script.charset = "UTF-8";
    head.appendChild(script);
    window[requestId]["scriptNode"] = script;

    //從新封裝回調函數,調用後應刪除script結點,刪除該請求信息。
    window[requestId]['callback'] = function(data) {
        try {
            options.callback && options.callback(data);
        } catch (e) {
            console.log(e);
        } finally {
            head.removeChild(window[requestId]["scriptNode"]);
            clearTimeout(window[requestId]["timer"]);
            delete window[requestId];
        }
    };

    // 超時調用
    window[requestId]["timer"] = setTimeout(function() {
        //拋出異常,並作異常處理
        try {
            throw new Error("over time");
        } catch (e) {
            if (options.fail) {
                options.fail(e.message);
            }
        }
        head.removeChild(window[requestId]["scriptNode"]);
        delete window[requestId];
    }, options.timeout);
}
相關文章
相關標籤/搜索