Using Promises with the JavaScript Client Object Model in SharePoint 2013

Scot Hillier

by Scot Hillier on 3/4/2013

Share this:
Print

Article Details

Date Revised:
12/21/2015

Applies to:
client object model, javascript, JSOM, promises, SharePoint 2013


Originally published 3/4/2013 and reproduced here for reference

I’ve discussed promises briefly in a previous post and have noticed that many SharePoint developers are starting to talk about them. If promises are new to you, read that short post first to come up to speed before continuing.

Promises allow an asynchronous call to return immediately, but with a “promise” to provide the data later. Promises most naturally fit in with the SharePoint 2013 REST API because the jQuery ajax() method already returns a promise so it’s pretty straightforward. In this post, however, I want to look at using promises in the JavaScript Client Object Model (JSOM) and show that it can work there as well.

Promises can make it easy to execute dependent asynchronous calls sequentially—a common requirement in app development. For this post, I’m going to show how to use promises and JSOM to first create a SharePoint list and then add items to the list. Obviously, the list must be created before the items can be added. Even though both the list creation and the item creation are asynchronous, promises will help us execute them in the desired sequence.

Let’s start with a library for creating a new SharePoint list using JSOM.

"use strict";

var WingtipToys = window.WingtipToys || {};
WingtipToys.Jsom = WingtipToys.Jsom || {};
WingtipToys.Jsom.Lists = function () {
var create = function (title, description, template) {
var deferred = $.Deferred();
var ctx = new SP.ClientContext.get_current();
var createInfo = new SP.ListCreationInformation();

createInfo.set_title(title);
createInfo.set_description(description);
createInfo.set_templateType(template);

this.newList = ctx.get_web().get_lists().add(createInfo);

ctx.load(this.newList);
ctx.executeQueryAsync(

Function.createDelegate(this,
function () { deferred.resolve(this.newList); }),
Function.createDelegate(this,
function (sender, args) { deferred.reject(sender, args); }));
return deferred.promise();
};
return {
create: create
};
}();

This library uses the standard ListCreationInformation object to create a new list. Notice, however, that the first line of the create function uses the jQuery $.Deferred() method to create a new deferred. The deferred object contains the promise. In the code, the new deferred object is added to an array and then the promise is returned from the asynchronous call. It’s important to understand that the promise is returned immediately—even before the asynchronous call is complete. The resolve() and reject() methods of the promise are subsequently executed when the executeQueryAsync() method completes depending upon the success or failure of the call.

Now take a closer look at the definition of the executeQueryAsync() method in the library. First, note the use of the Function.createDelegate() method to define the success and failure functions. This structure allows the definition of this to be passed into the success and failure functions. The pattern will allow us to access the newly created list after the call completes without having to save a globally-scoped variable (which is how you usually see it done). Second, notice that the resolve() method takes a parameter which references the newly-created list.

The following code can be used to call the library and create a new list.

WingtipToys.Jsom.Lists.create(
"Announcements1",
"A new Announcements List",
SP.ListTemplateType.announcements).then(
//create list success
function (newList) {
alert("Created list '" + newList.get_title() + "'");
},

//create list failure
function (sender, args) {
alert(args.get_message());
}
);

In the above code, notice how the call to the create() function is made followed by the use of the then() method. The then() method fires when the asynchronous call completes and executes either the first (success) or second (failure) function as appropriate. Also notice that the success function receives the newly created list, which it then uses to display a message with the list’s title. That is pretty cool.

Now that the list is created, we want to add a list item. First, we need a library to create the list item. The following code follows the same pattern as for the list creation. A promise is returned immediately, and the newly-created list item is returned if the asynchronous call is successful.

"use strict";
window.WingtipToys = window.WingtipToys || {};
WingtipToys.Jsom = WingtipToys.Jsom || {};
WingtipToys.Jsom.ListItems = function () {

var create = function (listName, itemTitle) {
var deferred = $.Deferred();
var ctx = new SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listName);

ctx.load(list);

var listItemCreationInfo = new SP.ListItemCreationInformation();

this.newItem = list.addItem(listItemCreationInfo);
this.newItem.set_item("Title", itemTitle);
this.newItem.update();

ctx.load(this.newItem);
ctx.executeQueryAsync(

Function.createDelegate(this,
function () { deferred.resolve(this.newItem); }),
Function.createDelegate(this,
function (sender, args) { deferred.reject(sender, args); }));
return deferred.promise();
};

//public interface
return {
create: create
}
}();

Now let’s take a look at how the calls are sequenced to ensure the list is created before the item is added.

WingtipToys.Jsom.Lists.create(
"Announcements1",
"A new Announcements List",
SP.ListTemplateType.announcements).then(

//create list success
function (newList) {
alert("Created list '" + newList.get_title() + "'");
WingtipToys.Jsom.ListItems.create(
newList.get_title(),
"A new announcement").then(

//create item success
function (newItem) {
alert("Created item '" + newItem.get_id() + "'");
},

//create item failure
function (sender, args) {
alert(args.get_message());
}
);
},

//create list failure
function (sender, args) {
alert(args.get_message());
}

);

Notice in the above code how the call to create a new item is nested in the success return from the list creation operation. Furthermore, notice how the returned list information is used in the subsequent call to create the list item. This is very clean and readable code that guarantees the correct sequence of events for our scenario. Even better, promises have allowed us to separate the general libraries used for list and item creation from the specific code that creates specific instances.

So it doesn’t matter if you prefer to use the SharePoint 2013 REST API or the classic JSOM approach that’s been around since 2010. Both approaches can—and should—make use of promises.


Topic: JavaScript and jQuery

Sign in with

Or register