如何提高xPage的typeAhead性能?

时间:2017-01-31 02:46:25

标签: javascript java xpages

这是我的inputText控件,启用了typeAhead:

<xp:inputText id="inputNameEditBox">
    <xp:typeAhead 
        mode="full" 
        minChars="3"        
        ignoreCase="true"
        valueList="#{javascript:return mytypeAheadList();}"
        var="searchValue" 
        valueMarkup="true" 
        id="typeAhead1">
    </xp:typeAhead>
</xp:inputText>

SSJS mytypeAheadList()函数调用自定义Java userTools.userLookup()函数来获取一组建议。 (我们的服务器无法访问公司目录,因此我们必须使用LDAP HTTP Java API。)

SSJS图书馆:

function mytypeAheadList(){
    var v=new userTools.userLookup();  //Java library
    var usrList = v.getUserList(searchValue);
    var lenList = usrList.length;
    var retList = "<ul>";

    if(lenList>0){
        for (var i=0; i<lenList; i++) { 
            var matchDetails:string = ["<li>",@Name("[ABBREVIATE]", @Left(usrList[i], "@")),"</li>"].join(""); 
            retList += matchDetails;
        }       
    } else {
        retList += ["<li>","None found","</li>"].join("");
    }

    retList += "</ul>"; 
    return retList;     
}

这意味着每次用户键入一个字符时都会创建userTools Java对象。有没有办法避免它,例如在页面加载时使var v成为全局变量?似乎范围变量不能接受Java对象。

2 个答案:

答案 0 :(得分:1)

我会做以下事情:

  1. Serializable 接口实现为 getUserLookup 返回的POJO。这允许将对象存储在 viewScope
  2. 限制 lenlist 的最大大小。例如。 20个结果将减少循环时间,HTTP响应的大小和浏览器中的性能
  3. 缓存搜索结果(将 searchValue 和生成的HTML字符串添加到地图中)。如果用户点击退格,则不得重新计算整个结果。
  4. 放弃SSJS。使用Java。
  5. 可选:如果可能,请预先计算结果。
  6. 修改 像这样:

    function mytypeAheadList(){
    
        // check if value is already cached
        if( viewScope.containsKey("search~" + searchValue) ){
            return viewScope.get("search~" + searchValue);
        }
    
        // get the userLookup object
        var v = null;   
        if( viewScope.containsKey("userLookup") ){
            v = viewScope.get("userLookup");
        }else{
            v = new userTools.userLookup();
            viewScope.put("userLookup", v);
        }
    
        // if usrList is "unlimited", limit the max size
        var usrList = v.getUserList(searchValue);
        var lenList = usrList.length > 20 ? 20 : usrList.length;
    
        // if getUserList has a restriction parameter
        var usrList = v.getUserList(searchValue, 20);
        var lenList = usrList.length;
    
        // build the list
        var retList = null;
    
        // reuse a variable is up to 2 times faster
        var matchDetails = null;
    
        if(lenList>0){
            retList = "<ul>";
            for (var i=0; i<lenList; i++) { 
                // concatenating a string is up to 2 times faster then join
                matchDetails = "<li>" + @Name("[ABBREVIATE]", @Left(usrList[i], "@")) + "</li>";
                retList += matchDetails;
            }
            retList += "</ul>"; 
        } else {
            // why join a static string?
            retList = "<ul><li>None found</li></ul>";
        }
    
    
        // put the result to the cache
        viewScope.get("search~" + searchValue, retList);
    
        return retList;     
    }
    

答案 1 :(得分:0)

是的,你可以这样做。

您可以将var v放在函数之外以保持其加载(并且只是通过检查它是否为null来延迟加载它。)

或者您可以将它全部放在Java bean中,并让bean的范围决定您希望保留数据的时间:ViewScope仅用于此页面 - ApplicationScope允许所有用户共享它(并且您可以构建检查强制最大年龄为xx分钟 - 这可能与您查看的数据是否可能发生变化有关。