协议管理平台 – 静态JSONP

协议配置平台中用了静态JSONP的方式解决问题;关于协议配置平台,参照这里,第一个就是。

JSONP原理

在页面上动态创建一个 script 标签,src 指向接口地址,将接口返回内容作为一段 js 执行;

接口返回内容格式为:callbackName(data),即 回调函数名称(需要传递的数据) 这种形式,其中,回调函数名称是页面调用接口时通过参数传过来的,参数名一般为 callback 或 cb;

页面在动态创建 script 标签之前,按照约定的规则或名称注册全局的回调函数;当接口返回内容时,会作为 js 执行,调用回调函数,将数据传入函数内部;

静态JSONP接口

第一部分中,回调函数名称是由页面决定的,网页传什么名称,服务端就返回什么名称;

如果接口/js文件是一个静态的呢,回调函数名称肯定也只能写死,按照上面的逻辑,如果写死了回调函数名称,整个流程并未受到影响;

为什么用静态文件做接口?

团队内部并没有后端开发,部署一套稳定的线上 JSONP 转换接口成本太高(申请服务器、开发、接入云存储、部署,坑太多);

协议配置平台中,word 可以转为 html,如果将格式化好的 html 包装成 jsonp 格式,做成一个静态的 js 文件,页面就可以通过一个写死的回调函数名称动态获取到 html 的内容了。

这样就可以解决某些场景下的问题:活动页中,活动规则用弹框的形式展现,内容想要动态配置,还不想用iframe

协议配置平台中,每一个文件上传之后,都会进行重命名,名称是用 UUID 进行替换的 (项目实际用的时候,把中间的连字号去掉了,只保留了32位数字字母;严格说来,还不是标准的UUID)。

维基百科中UUID的定义:

UUID 基本可以认为是唯一的,作为文件名是没有问题的,将此 UUID 稍作修改,也可以作为回调函数名称;这样,文件名和回调函数也能保持统一;

项目中,用了 “cb_uuid” 来作为回调函数名称,JSONP对应的 js 文件名也是同一个 UUID:

调用的相关代码

如果引用了 jquery 或 zepto,直接配置回调函数名就可以调用了:

var url = '//a.com/protocols/jsonp/69d9d29d6b7b536833edceadee954d82.js';
$.ajax({
    url: url,
    dataType: "jsonp",
    jsonpCallback: "cb_69d9d29d6b7b536833edceadee954d82",
    success: function (result) {
        console.log(result);
    },
    error: function () {
    }
});

或者用原生 js 封装一下:

;(function () {
    window.loadRuleCont = function (opts) {
        opts = opts || {};
        opts.timeout = opts.timeout || 5000;
        var jsonpUrl = opts.url;
        var success = opts.success;
        var error = opts.error;
        var timer = null;
        var data = opts.data;
        var noArgsUrl = jsonpUrl.split("?")[0];
        var name = noArgsUrl.replace(/[\s\S]+jsonp\/([\s\S]+)\.js/gmi, "$1");    // /jsonp/21ac67e6e4ceaf1d073d6688f435abbd.js
        var cbName = "cb_" + name;
        var head = document.getElementsByTagName("head")[0];
 
        window[cbName] = function (result) {
            success && success(result);
            window[cbName] = null;
            clearTimeout(timer);
        };
 
        var script = document.createElement("script");
        script.src = jsonpUrl;
        head.appendChild(script);
 
        timer = setTimeout(function () {
            window[cbName] = null;
            head.removeChild(script);
            error && error("");
        }, opts.timeout);
    }
})();

调用上面封装的方法:

var url = '//a.com/protocols/jsonp/69d9d29d6b7b536833edceadee954d82.js';
window.loadRuleCont({
    url: url,               // jsonp地址,从协议列表后的jsonp按钮获得
    timeout: 2000,      // 超时时间
    success: function (html) {
        console.log(html)
    },
    error: function () {
    }
});

如果这篇文章对你有用,可以点击下面的按钮告诉我

0

发表回复