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();
    };
  • What lines throws the error? The resolve? – wjervis Oct 21 '14 at 12:04
  • var listItemEnumerator = camlItems.getEnumerator(); throws error. – Nadeem Yousuf Oct 21 '14 at 12:06
  • Isn't this changed in the delegate? Why not use a var items = as you do in your first code snippet? – Robert Lindgren Oct 21 '14 at 12:12
  • @RobertLindgren, that solved the issue. Can you please add it as an answer. – Nadeem Yousuf Oct 21 '14 at 12:18
  • Great! I added it as an answer now – Robert Lindgren Oct 21 '14 at 12:21
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, privacy policy and cookie policy

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