Promise promise
Introduction
In a lot of front-end SharePoint code that we write, we use asynchronous calls (ajax). For example, with JSOM (JavaScript Object Model), a Microsoft-generated collection of libraries that serve as a proxy to the server-side object model. But also when we call SharePoint’s REST API.
During a job I encountered a complex set of nested JavaScript calls with callbacks in which calls with callbacks were called. Since JSOM calls are asynchronous, we sometimes encounter situations like this.
What can help make it clearer is to work with JavaScript promises.
Below I will explain this and work out a solution for SharePoint.
What is a promise?
By a “promise” we mean here “an object that may in the future return a single value: a resolved value or a reason that it has not been resolved (for example, a network error has occurred). A promise can be in one of the three possible states are: fulfilled, rejected, or pending.
What do you need?
There are various options for using promises in your SharePoint solution:
- Bluebird (https://github.com/petkaantonov/bluebird)
- jQuery’s
- Angular promises: https://azamkhaan.blogspot.com/2016/06/sharepoint-2013-crud-operations-using.html
- ReactJS also contains a promise object
- Native promises (unless you also want to support IE):
The JavaScript Promise object is available by default in EcmaScript.
Since Internet Explorer does not have “native promise support” for promises and we still often want to support this browser, preference will soon be given to, for example, the jQuery or Angular variant and not the standard EcmaScript Promise object.
Below is an example of a native Promise (note: this does not work in IE):

Example: native EcmaScript Promise (does not work in IE)
The same example looks like this with jQuery’s “Deferred” function:

Example: jQuery’s “Deferred” function
Nested promises and the Christmas tree
The following code example in AngularJS proves that the use of promises cannot automatically prevent a Christmas tree structure from occurring:

Example: Nested promises and the Christmas tree
Taking down the Christmas tree
In AngularJS I converted the above Christmas tree structure into the following setup, using the q.all function:

Example: broken-down Christmas tree with AngularJS “q.all” function
The result is a lot clearer.
In addition, it saves 2 seconds in loading time, because all asynchronous calls are kicked off in parallel instead of sequentially.
$when.apply
What is done in AngularJS by the q.all function is done in jQuery by $when.apply.
Using jQuery’s “Deferred” function together with the $when.apply function provides a handy combination to create multiple promises and, once they’ve all been addressed, continue working with the result. The following code shows this:

Example: jQuery’s “when.apply” function to process multiple promises
The following can be concluded:
Line 3 retrieves the followed sites with a promise.
Once this is fulfilled or rejected, the result is continued in the “then” callback function. This happens respectively in the success argument on line 5 or in the error argument on line 41.
In the success callback, an object is created on line 7 to hold the data.
The news is then retrieved for each followed site in the form of a promise object and we store it in an array.
On line 16 we see the $when.apply construct come into play.
We put the array with promises in here and once these have all been fulfilled we can continue with the result in the success argument of the “then” callback function.
We first create an array on line 18 to store the news objects.
The arguments variable contains the result of all fulfilled promises. We go through this per promise and discuss this in the callback of the jQuery each function. On line 24 we collect the news data by storing it in the previously created array.
If an error occurred while processing all promises, we can accommodate this in the error argument of the then callback function. Finally, there is the always callback function in which we can do something at any time, if all promises have been completed regardless of an error. This can be compared to “finally” in the C# try/catch/finally construct.
By the way, the call to the function to retrieve the news promise object goes as follows:

Example: returning a promise object with jQuery’s “Deferred” object.
The creation of a “deferred” object starts on line 2.
In the success callback of the ajax function we fulfill the promise with the resolve function on line 35.
In the error callback of the ajax function we reject the promise of the reject function on line 38.
Before this happens, the function has already returned the promise object as a “handle” to the calling function, so it can be waited for.
End result
In the image below you can see that the news from the followed sites is shown.
A promise call was therefore made for each site followed. Only after all calls had been processed was the retrieved data shown.

Example: end result of multiple asynchronous calls in the browser
Delegate functions and context
In the code examples above, each time code blocks were passed as success and error callbacks to the asynchronous functions.
The example below shows that this is also possible with delegate functions:

Example: delegate functions and passing a promise
What is especially important to realize here is that an object (objectContainer) is passed to the delegate function on line 12. This changes the “this” context in the delegate in the passed object (see lines 21 and 26).
In this way we provide the deferred object to fulfill or reject the promise, but also the object that we want to load asynchronously and do something with.
Finally
This way it becomes easier to make multiple calls to SharePoint with JSOM, while the code remains clear and readable.
In addition, loading time is quickly saved, because all asynchronous calls are kicked off in parallel instead of sequentially.
Performance always remains an interesting challenge in these types of asynchronous scenarios with multiple calls. This can be conveniently measured by adding the following lines of code at the start and end moments with JavaScript:

Example: measuring performance with JavaScript
References
If you would like to know more about promises, here are some references:
- Clear blog post about promises: https://blackninjasoft.com/blog/using-jquery-promises-deferreds-with-sharepoint-2013-jsom
- Fundamentals: https://developers.google.com/web/fundamentals/primers/promises
- http://alistapart.com/article/getoutbindingsituations
- https://scotch.io/tutorials/javascript-promises-for-dummies
- Nice explanation of promises using a strip and AngularJS: http://andyshora.com/promises-angularjs-explained-as-cartoon.html
Geef een reactie