Jsonp的理解

一生装逼成今日,四海无人对夕阳。

##JSONP的理解

说来惭愧,以前只知道用jsonp跨域,src和iframe能跨域,原生jsonp是怎么实现的呢,我却木有思考过

到了邮件这边以后,遇到了不能用第三方库用原生写跨域的需求,研究了一下jsonp

现在才知道,jsonp实际上是先声明一个回调函数,利用<script>标签的src来跨域请求返回一段js代码执行,而这个执行的代码是要放在这个事先声明的函数里的

因为有时不能和后台固定死一个回调函数名,所以在window下注册一个全局变量来接受函数名就可以实现动态定义回调函数了

以下是代码实现

    /**
     * 获取js脚本
     * @method getScript
     * @param {string}_url 请求url
     * @param {function}_callback 回调函数
     * @return {void}
     */
    _getScript: function(_url, _charset, _callback, _error) {
        // 异步加载解决
        setTimeout(function() {
            var READY_STATE_RE = /loaded|complete|undefined/;
            var script = document.createElement("script");
            script.setAttribute("charset", _charset || "utf-8");
            script.setAttribute("type", "text/javascript");
            script.setAttribute("src", _url);
            script.async = "async";
            var callback = function(_status) {
                if (READY_STATE_RE.test(script.readyState)) {
                    script.onload = script.onerror = script.onreadystatechange = null;
                    script.parentNode.removeChild(script);
                    script = undefined;
                    //IE10下新加载的script会在此之后执行,所以此处需延迟执行
                    // 成功
                    if (_status) {
                        if (typeof _callback == "function") {
                            setTimeout(_callback, 0);
                        }
                    } else {
                        // 有error的时候使用error
                        if (typeof _error == "function") {
                            setTimeout(_error, 0);
                        } else if (typeof _callback == "function") {
                            setTimeout(_callback, 0);
                        }
                    }
                }
            };

            script.onload = function() {
                callback(true);
            };
            script.onerror = function() {
                callback(false);
            };
            script.onreadystatechange = function() {
                callback(true);
            };

            var head = document.getElementsByTagName("head")[0];
            head.appendChild(script);
        }, 0);
    }

    /**
     * 模拟jsonp
     * @deprecated 已经废弃,一般使用跨域ajax调用
     */
    jsonp: function(_url, _callback, _settings) {
        var settings = $.extend({
            charset: "utf-8"
        }, _settings);
        var funcName = "_tmp_jsonp_callback" + (+new Date);
        if (settings.funcName) {
            funcName = settings.funcName;
        }
        window[funcName] = function() {
            _callback && _callback.apply(window, arguments);
            try {
                delete window[funcName];
            } catch (e) {}
        }
        var callbackObj = {};
        callbackObj[(settings.callbackName || "callback")] = funcName;
        // _settings里面加入自定义callbackname,for文件中心里面不是用callback作为回调函数名。
        var url = this.appendURL(_url, callbackObj);
        this.getScript(url, settings.charset, function() {
            // _callback && _callback.apply(window,arguments);
            try {
                window[funcName]();
                // 删除临时变量
                delete window[funcName];
            } catch (e) {}
        });
    }

    

AsteriskYk - 猪场前端搬砖 in categories web  tagged with javascript