当前位置: 移动技术网 > IT编程>开发语言>JavaScript > JSONP原理及简单实现教程

JSONP原理及简单实现教程

2018年04月04日  | 移动技术网IT编程  | 我要评论

欧庆春,邯郸生活资讯,内心独白

JSONP原理及简单实现

JSONP原理

利用<script>标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址(src属性)指向第三方的API网址,并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。例如: <script src="https://www.example.net/api?param1=1¶m2=2"></script>

第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),例如:

callback(json数据)这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。

举个简单的例子:

首先用node搭建一个服务器:

'use strict';
//通过require将http库包含到程序中
var http = require('http');
//引入url模块解析url字符串
var url = require('url');
//引入querystring模块处理query字符串
var querystring = require('querystring');
//创建新的HTTP服务器
var server = http.createServer();
//通过request事件来响应request请求
server.on('request',function(req, res){
    var urlPath = url.parse(req.url).pathname;
    var qs = querystring.parse(req.url.split('?')[1]);
    if(urlPath === '/jsonp' ){
        res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'});
        var data = {
            "name": "JSONP"
        };
        data = JSON.stringify(data);
        var callback = qs.callback+'('+data+');';
        res.end(callback);
    }
    else{
        res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
        res.end('Hell World\n');    
    }    
});
//监听8088端口
server.listen('8088');
//用于提示我们服务器启动成功
console.log('Server running!');

然后,创建一个页面

<script>
   function test(data){alert(data.name);};
</script>
<script src="https://127.0.0.1:8088/jsonp?callback=test"></script>

JSONP简单实现

基本思路:

1. 根据传入的url、参数拼接成完整的url,可以为url提供一个时间戳来避免浏览器缓存

2. 把传入的回调函数作为callback参数补充到传入的URL(真正要访问的跨域的URL)中

3. 动态创建出script元素并触发URL的访问。浏览器获取返回的JS代码并执行,也就是执行了传入的回调函数。

核心代码:

JSONP.prototype = {
        // 时间戳,避免浏览器缓存
        now:function() {
            return (new Date()).getTime();
        },
        // 删除节点
        removeElem:function(elem) {
            var parent = elem.parentNode;
            if(parent && parent.nodeType !== 11) {
                parent.removeChild(elem);
            }
        },
        // 拼接url参数
        parseParam:function() {
            var param="",data = this.options;
            if("string" === typeof data) {
                param = data;
            }else if("object" === typeof data) {
                for(var item in data) {
                    param += "&" + item + "=" + encodeURIComponent(data[item]);
                }
            }
            param += "&_stamp=" + this.now();
            return param;
        },

        getJSONP:function() {
            var id = (this.options.name || '__jp') + (count++);
            this.url += "?";
            this.url +=  this.parseParam();
            this.url = this.url.replace('?&', '?');
            if(this.fn) {
                this.url += "&callback=" + this.fn;
            }
            // 创建一个script元素
            var script = document.createElement("script");
            script.type = "text/javascript";
            // 设置要远程的url
            script.src = this.url;
            // 设置id,为了后面可以删除这个元素
            script.id = id;
            var _this = this;
             // 把传进来的函数重新组装,并把它设置为全局函数,远程就是调用这个函数
            window[id] = function(json) {
                // 执行这个函数后,要销毁这个函数
                window[id] = undefined;
                // 获取这个script的元素
                var elem = document.getElementById(id);
                // 删除head里面插入的script,这三步都是为了不影响污染整个DOM啊
                _this.removeElem(elem);
                // 执行传入的的函数
                _this.fn(json);
            };

            // 在head里面插入script元素
            var head = document.getElementsByTagName("head");
            if(head && head[0]) {
                head[0].appendChild(script);
            }
        }
    };

应用方式:

还是利用刚才的服务器,然后在页面引用并使用:

new JSONP({

url:url,

data:data,

callback:callback

})

url是后端地址,data是参数,即url链接“?”后的内容(可选),callback是回调函数。

<script src="jsonp.js"></script>
<script>
    function test(data){alert(data.name);};
    var data = {
            output: "json"
        }
    new JSONP({
        url:"https://127.0.0.1:8088/jsonp",
        data:data,
       callback:"test"
    });
 </script>

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网