一个未初始化的属性......但它应该是?

时间:2014-10-23 14:35:47

标签: javascript sharepoint initialization

我有一个包含文件夹的列表,我正在尝试获取这些文件夹中文件总数的计数。

我设法检索包含我的文件夹的ListItemCollection。然后它开始......挑剔。

ctx是我的ClientContext,collection是我的ListItemCollection。

function countFiles()
{
    var enumCollection = collection.getEnumerator();

    while(enumCollection.moveNext())
    {
        currentItem = enumCollection.get_current();

        var folder = currentItem.get_folder();

        if (folder === 'undefined')
            return;

        ctx.load(folder, 'ItemCount');
        ctx.executeQueryAsync(Function.createDelegate(this, function()
            {
                totalCount += folder.get_itemCount();
            }), Function.createDelegate(this, onQueryFailed));
    }
}

所以它有效......一半时间。如果我的集合中有6个项目,我会得到3或4个“属性或字段'ItemCount'尚未初始化”异常,显然我的totalCount是错误的。我似乎无法理解为什么,因为executeQueryAsync不应该在文件夹实际加载之前发生。

我对Javascript很新,所以它可能看起来很可怕,并且缺少一些我认为不值得关注的基本代码,请随时询问是否是这样。

2 个答案:

答案 0 :(得分:1)

从异步回调引用闭包变量(在本例中为folder)通常是一个大问题。谢天谢地,这很容易解决:

function countFiles()
{
    function itemCounter(folder) {
        return function() { totalCount += folder.get_itemCount(); };
    }

    var enumCollection = collection.getEnumerator();

    while(enumCollection.moveNext())
    {
        var folder = enumCollection.getCurrent().get_folder();

        if (folder === undefined) // not a string!
            return;

        ctx.load(folder, 'ItemCount');
        ctx.executeQueryAsync(itemCounter(folder), Function.createDelegate(this, onQueryFailed));
    }
}

(您不需要.createDelegate()调用,因为该函数不需要this。)

现在,在此之后,您将面临知道该计数器何时最终更新的问题。那些异步回调最终会完成,但什么时候?您可以保留一个单独的计数器,一个用于您启动的每个查询,然后在回调中减少该计数器。当它回落到零时,你就会知道你已经完成了。

答案 1 :(得分:1)

由于SP.ClientContext.executeQueryAsync是一个 async 函数,因此很可能在第一次调用回调函数之前终止循环,因此指定代码的行为可能是意外的。

相反,我建议使用SharePoint JSOM计算文件(包括位于嵌套文件夹下的文件)的另一种更干净的方法。

如何使用JSOM

计算List中的文件总数

以下功能允许计算列表中的列表项数:

function getItemsCount(listTitle, complete){
    var ctx = SP.ClientContext.get_current();
    var list = ctx.get_web().get_lists().getByTitle(listTitle);
    var items = list.getItems(createQuery());
    ctx.load(items);
    ctx.executeQueryAsync(
      function() {
          complete(items.get_count());
      },
      function() {
         complete(-1);
      }   
    );

    function createQuery()
    {
        var query = new SP.CamlQuery();
        query.set_viewXml('<View Scope="RecursiveAll"><Query><Where><Eq><FieldRef Name="FSObjType" /><Value Type="Integer">0</Value></Eq></Where></Query></View>');
        return query;
    }
}

用法

getItemsCount('Documents', function(itemsCount){
    console.log(String.format('Total files count in Documents library: {0}',itemsCount));
});