1

I have following piece of SharePoint JavaScript client object code which works perfectly without throwing any error.

$(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });

    function prepareTables() {
        for (var i = 0; i < 3; i++) {
            getItemsWithCaml('External User Account Request',
                function (camlItems) {
                    var listItemEnumerator = camlItems.getEnumerator();
                    while (listItemEnumerator.moveNext()) {
                        var listItem = listItemEnumerator.get_current();
                        console.log(listItem.get_item('Title'));
                    }
                },
                function (sender, args) {
                    console.log('An error occured while retrieving list items:' + args.get_message());
                });
        }
    }    

    function getItemsWithCaml(listTitle, success, error) {
        var clientContext = new SP.ClientContext.get_current();
        var list = clientContext.get_web().get_lists().getByTitle(listTitle);
        var camlQuery = new SP.CamlQuery();
        var camlItems = list.getItems(camlQuery);
        clientContext.load(camlItems);
        clientContext.executeQueryAsync(
                function () {
                    success(camlItems);
                },
                error
            );
    };

However, if I replace the same code to use deferreds/promises I get collection has not been initialized error:

The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

Following is the code using deferreds:

$(document).ready(function () {
        //don't exectute any jsom until sp.js file has loaded.        
        SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
    });    

    function prepareTables() {
        for (var i = 0; i < 3; i++) {
            getItemsWithCaml('External User Account Request').then(
                function (camlItems) {
                    var listItemEnumerator = camlItems.getEnumerator();
                    while (listItemEnumerator.moveNext()) {
                        var listItem = listItemEnumerator.get_current();
                        console.log(listItem.get_item('Title'));
                    }
                },
                function (sender, args) {
                    console.log('An error occured while retrieving list items:' + args.get_message());
                }
            );              
        }
    }    

    function getItemsWithCaml(listTitle) {
        //use of $.Deferred in the executeQueryAsync delegate allows the consumer of this method to write 'syncronous like' code
        var deferred = $.Deferred();

        var clientContext = new SP.ClientContext.get_current();
        var list = clientContext.get_web().get_lists().getByTitle(listTitle);

        var camlQuery = new SP.CamlQuery();        
        this.items = list.getItems(camlQuery);

        clientContext.load(this.items);

        clientContext.executeQueryAsync(
            Function.createDelegate(this,
                function () { deferred.resolve(this.items); }),
            Function.createDelegate(this,
                function (sender, args) { deferred.reject(sender, args); }));

        return deferred.promise();
    };
5
  • What lines throws the error? The resolve?
    – wjervis
    Commented Oct 21, 2014 at 12:04
  • var listItemEnumerator = camlItems.getEnumerator(); throws error. Commented Oct 21, 2014 at 12:06
  • Isn't this changed in the delegate? Why not use a var items = as you do in your first code snippet? Commented Oct 21, 2014 at 12:12
  • @RobertLindgren, that solved the issue. Can you please add it as an answer. Commented Oct 21, 2014 at 12:18
  • Great! I added it as an answer now Commented Oct 21, 2014 at 12:21

1 Answer 1

1

It could be an issue with this, since it changes scope when you use it in the delegates, try using var items= list.getItems(camlQuery) as you do in your first snippet:

function getItemsWithCaml(listTitle) {
    //use of $.Deferred in the executeQueryAsync delegate allows the consumer of this method to write 'syncronous like' code
    var deferred = $.Deferred();

    var clientContext = new SP.ClientContext.get_current();
    var list = clientContext.get_web().get_lists().getByTitle(listTitle);

    var camlQuery = new SP.CamlQuery();        
    var items = list.getItems(camlQuery); // changed to local variable

    clientContext.load(items); //changed to load the variable

    clientContext.executeQueryAsync(
        Function.createDelegate(this,
            function () { deferred.resolve(items); }), // return the variable
        Function.createDelegate(this,
            function (sender, args) { deferred.reject(sender, args); }));

    return deferred.promise();
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.