zoukankan      html  css  js  c++  java
  • 从Domino公式@DBLookup Web化谈如何实现通用函数

    我以前实现的@DBLooup AJAX版,都是通过URL带参数,执行后台代理,并返回结果的方式。最近在实现一个应用模块时,看到我们公司同事的实现方式,觉得比我的更好一些,但有些缺陷。特此将代码贴出来供大家参考。具体的JS代码如下: 

    01function dblookup(view,skey,column){  
    02    try{  
    03        var url = getPath()+"/"+view+"?readviewentries&restricttocategory="+skey;  
    04        objHTTP = new ActiveXObject("Microsoft.XMLHTTP");  
    05        //下面用get方法,在get方法中,代理取传过去的参数是用doc.query_string(0)  
    06        objHTTP.open("GET", vurl, false, "", "");  
    07        objHTTP.setRequestHeader("If-Modified-Since","0");  
    08        objHTTP.send(false);  
    09        //此处调用的是同步方法  
    10        resp = objHTTP.responseXML.documentElement;  
    11        objHTTP = null;  
    12        var ss="";  
    13        if (resp.hasChildNodes()) {  
    14            NodeList = resp.getElementsByTagName("viewentry")  
    15            for (var k=0;k
    16                NodeList1=NodeList(k).getElementsByTagName("entrydata");  
    17                mynode=NodeList1(column-1).firstChild;  
    18                mynode1=mynode.firstChild;  
    19                ss= mynode1.nodeValue;  
    20                break;  
    21              }  
    22          }else{  
    23                ss="";  
    24          }  
    25    }catch(e){  
    26        ss="";  
    27    }  
    28    return ss;  
    29}

    以上代码在使用URL请求视图时,使用restricttocategory进行分类限制,这样可以得到以skey为分类的视图,再通过返回的XML文档,对其进行解析得到视图中第一份文档指定列(column)中的值,并返回给调用者;

    如果你想返回多个文档的指定列值,将: 
                    ss= mynode1.nodeValue; 
                    break; 
          修改为: 
                    ss+=";"+mynode1.nodeValue; 
          即可。但需要注意,视图缺省只返回20个文档,相关设置在服务器文档中设置。需要返回超过20个文档时,你可以在请求的URL中加入count参数来指定需要返回文档的个数。

    此函数缺点不利于扩展,假如dblookup函数已在项目中或产品模块实施,但现在需要将其功能进行扩展,加入跨库和跨服务器功能时,如果修改dblookup函数参数,则肯定会影响到现在项目中或产品模块中相关的JS代码,对升级或更新造成了不少的工作量,这些工作量又是重复的。这种情况下通常选择的是新增另一个函数,如dblookup_pro,这样会使封装的JS文件多一些冗余代码,从而增加JS文件尺寸。当然你会说,增加一个函数并不会增加JS文件多少尺寸,但你想想,都抱着这个心态,JS中这扩展点,那补充点。经过长期团队成员的修改和项目积累,会使用封装的JS文件会越来越大,到达一种冗余代码过多,但又不得不用的状态。所以我一直强调在设计通用代码时,一定要适当考虑代码容错和以后的功能扩展对现有代码的影响。这样会给今后代码维护带来非常小的工作量,虽然前期在写代码考虑的事情非常多,但你如果习惯了这种代码编写风格,会规范你的代码,提高你代码的质量,这不是每位程序员所追求的吗?

    但以上代码看似正常,能运行很好。但并没有容错代码,如HTTP请求失败,视图不存在怎么办?从代码上看返回的是空值,但这个是正确的返回结果吗?但如果出现以下情况,就会出现不可估量问题:

    在提交文档时,如果调用dblookup,会有可能因为网络延时造成,未返回结果就已提交文档了。如下代码片断:

    1......  
    2document.forms[0].UserCN.value = dblookup(‘vwAllUsers’,'SquallZhong',2);  
    3document.forms[0].submit();

    以上代码有可能让UserCN的值为空,如果在WebQuerySave()事件中有读UserCN域的值对文档进行处理,会造成程序上的运行错误。

    对dblookup进行改进后,代码如下:
    01function dblookup() {  
    02    //返回字符串  
    03    var ret = null;  
    04    //视图别名  
    05    var vn = arguments[0];  
    06    if (vn == null || vn == "") {  
    07        alert("\u8bf7\u6307\u5b9a\u89c6\u56fe\u522b\u540d\uff01");  
    08        return ret;  
    09    }  
    10    //关键字  
    11    var key = arguments[1];  
    12    if (key == null || key == "") {  
    13        alert("\u8bf7\u6307\u5b9a\u5173\u952e\u5b57\uff01");  
    14        return ret;  
    15    }  
    16    //指定列名  
    17    var col = arguments[2];  
    18    if (col == null || col == "") {  
    19        alert("\u8bf7\u6307\u5b9a\u5217\u503c\uff01");  
    20        return ret;  
    21    }  
    22    //回调函数  
    23    var func = arguments[3];  
    24    //指定数据库路径,数据库路径请使用Apps/DB.nsf。  
    25    //不论在WINDOW平台还是LINUX平台,在Domino平台中可使用"/"通用,并兼容URL格式  
    26    var dbpath = arguments[4];  
    27    //如果未指定数据库路径,则取当前路径  
    28    if (dbpath == null || dbpath == "") {  
    29        dbpath = getPath();  
    30    }  
    31    //将数据库路径中""转换为"/"  
    32    dbpath = dbpath.replace("\\", "/");  
    33    //指定数据库所在服务器名称,如AS1/ACME  
    34    var svr = arguments[5];  
    35    try {  
    36        var url = "";  
    37        if (svr == null || svr == "") {  
    38            url = "/" + dbpath + view + "?readviewentries&restricttocategory=" + skey;  
    39        } else {  
    40            //如果为跨DOMINO服务器请求,使用后台代理处理跨服务器请求  
    41            url = "/vgoresource.nsf/dblookup?openagent&login";  
    42            url += "&vn=" + vn;  
    43            url += "&key=" + key;  
    44            url += "&col=" + col;  
    45            url += "dbpath=" + dbpath;  
    46            url += "svr=" + svr;  
    47        }  
    48        // 避免IECache,添加时间戳  
    49        url += "&__t=" + Math.random();  
    50        var objHTTP = null;  
    51        if (window.XMLHttpRequest) {  
    52            // 创建 Mozilla/FireFox平台的 XMLHttpRequest 对象  
    53            objHTTP = new XMLHttpRequest();  
    54        } else {  
    55            if (window.ActiveXObject) {  
    56            // 创建 IE/Windows 平台的XMLHttp对象  
    57                objHTTP = new ActiveXObject("Microsoft.XMLHTTP");  
    58            }  
    59        }  
    60        objHTTP.open("GET", url, false);  
    61        objHTTP.onreadystatechange = function () {  
    62            if (objHTTP.readyState == 4) {  
    63                if (objHTTP.status == 200) {  
    64                    //如果有回调函数  
    65                    if (callback != null) {  
    66                        var resp = objHTTP.responseXML.documentElement;  
    67                        if (resp.hasChildNodes()) {  
    68                            var NodeList = resp.getElementsByTagName("viewentry");  
    69                            for (var k = 0; k < NodeList.length; k++) {  
    70                                NodeList1 = NodeList(k).getElementsByTagName("entrydata");  
    71                                mynode = NodeList1(column - 1).firstChild;  
    72                                mynode1 = mynode.firstChild;  
    73                                ret = mynode1.nodeValue;  
    74                            }  
    75                        } else {  
    76                            ret = null;  
    77                        }  
    78                        callback(ret);  
    79                    } else {  
    80                        //如果没有回调函数,直接返回文本  
    81                        return objHTTP.responseText;  
    82                    }  
    83                } else {  
    84                    return null;  
    85                }  
    86            }  
    87        };  
    88        objHTTP.send(null);  
    89    } catch (e) {  
    90        return null;  
    91    }  
    92}

    经过整改后的代码,可实现: 

    dblookup(view,keystring,column-num[,callback-function[,dbpath[,servername]]]
    view:视图别名 
    keystring:关键字查询 
    column-num:指定列数 
    callback-function:回调函数(可选) 
    dbpath:指定数据库路径(可选),缺省为当前数据库 
    servername:指定Domino服务器名称(可选),缺省为当前服务器;注:指定服务器名称时,请不要使用CN=Apps/O=ACME,这样在URL地址相加时会认为是两个参数,所以指定服务器名称时请使用Apps/ACME 
    方括号中为可选参数。这样可兼容以前项目所使用的dblookup(view,keystring,column-num),不需要维护已有WEB应用中调用的格式,也能实现回调函数处理功能/跨库/跨服务器功能。 
    有了回调函数功能,可避免在AJAX请求未完成之前,执行下面的代码,从而提高了代码的容错性,如下列代码:

    01.......  
    02function savedoc() {  
    03    //查询是否已定义过,并回调继续提交函数  
    04    var key = f.StServerName.value + "!!" + f.StDBPath.value;  
    05    key = key.split("\\").join("/");  
    06    dblookup("ArchivePolicyViewByFullDBPath", key.toLowerCase(), 1, submitdoc);  
    07}  
    08function submitdoc() {  
    09    var ret = arguments[0];  
    10    var f = document.forms[0];  
    11    if (ret == null) {  
    12        f.submit();  
    13    } else {  
    14        alert("此数据库的归档策略已定义,请重新输入数据库路径!");  
    15        f.StDBPath.select();  
    16        f.StDBPath.focus();  
    17    }  
    18}

    后续问题考虑:

    1.dblookup函数中处理是使用XML文档解析方式,如果你使用的Domino服务器是7.0以上版本,建议使用JSON来处理数据,这样效率要比XML解析效率高。如果使用JSON来处理数据,需要将视图输出格式修改为JSON输出,只需要将以下代码: 
    url = "/" + dbpath + view + "?readviewentries&restricttocategory=" + skey; 
    修改为: 
    url = "/" + dbpath + view + "?readviewentries&outputformat=json&restricttocategory=" + skey; 
    注:还需要修改对JSON数据的解析方式

    2.此函数功能,并未实现根据关键字查询相应文档所指定的域名,如果哪位朋友有兴趣可以实现一下。

    3.Domino中视图设置,视图中第一列必须为分类列,如果第一列不是分类列,是查不出结果的。如下图: 
    image

    4.对于封装的JS文件,建议对其进行混淆和压缩,来提高Javascript的安全性和JS在网络中的传输速度。

    参考资料:

    1.JS混淆压缩工具:http://blog.csdn.net/SquallZhong/archive/2008/11/29/3410592.aspx

    2.WEB性能优化及考虑:http://blog.csdn.net/SquallZhong/archive/2008/08/25/2826429.aspx

     

    •  
      •  
        •  
          •  
  • 相关阅读:
    CF 461B Appleman and Tree
    POJ 1821 Fence
    NOIP 2012 开车旅行
    CF 494B Obsessive String
    BZOJ2337 XOR和路径
    CF 24D Broken robot
    POJ 1952 BUY LOW, BUY LOWER
    SPOJ NAPTIME Naptime
    POJ 3585
    CF 453B Little Pony and Harmony Chest
  • 原文地址:https://www.cnblogs.com/hannover/p/2062008.html
Copyright © 2011-2022 走看看