We know that SharePoint JavaScript client object model is asynchronous. However, sometimes we want to process things in synchronous way. This can be done by using JavaScript call backs and deferreds/Promises. Let's first see an asynchronous example which we will later convert to synchronous:
As is clear the from the output, the code execution moves immediately to line console.log('Completed table prparation.');. It doesn't wait for method getItemsWithCaml(listTitle) to complete.
Now given below is an example using call backs.
<script type="text/javascript">
var camlItems;
$(document).ready(function () {
//don't exectute any jsom until sp.js file has loaded.
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
});
function prepareTables() {
getItemsWithCaml('External User Account Request');
console.log('Completed table prparation.');
}
function getItemsWithCaml(listTitle) {
var clientContext = new SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle(listTitle);
var camlQuery = new SP.CamlQuery();
camlItems = list.getItems(camlQuery);
clientContext.load(camlItems);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
};
function onQuerySucceeded(sender, args) {
var listItemEnumerator = camlItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var listItem = listItemEnumerator.get_current();
console.log(listItem.get_item('Title'));
}
}
function onQueryFailed(sender, args) {
console.log('An error occured while retrieving list items:' + args.get_message());
}
</script>
The External User Account Request list has two items in it. If I press F12 and check the log, I see the following output:Console Output |
Now given below is an example using call backs.
$(document).ready(function () {
//don't exectute any jsom until sp.js file has loaded.
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
});
function prepareTables() {
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'));
} console.log('Completed table prparation.');
},
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
);
};
Here is the output of the above script.
And here is same example using deferreds/Promises. It gives same output as callbacks.
Console Output |
$(document).ready(function () {
//don't exectute any jsom until sp.js file has loaded.
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', prepareTables);
});
function prepareTables() {
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'));
} console.log('Completed table prparation.');
},
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();
var items = list.getItems(camlQuery);
clientContext.load(items);
clientContext.executeQueryAsync(
Function.createDelegate(this,
function () { deferred.resolve(items); }),
Function.createDelegate(this,
function (sender, args) { deferred.reject(sender, args); }));
return deferred.promise();
};