Geeks With Blogs
Thorvald Bøe
The title of my first blog post could possibly have been taken from a poorly written love song, but it's not. Instead it is from some (hopefully not so poorly written) javascript code.

Ok, so this javascript world is kind of new to me. Not that I haven't used javascript for the last 13 years or so, it's more that my acceptance of javascript as a full fledged development tool is kind of new to me. With javascript libraries popping up all over and it being promoted as a knight in shiny armour to recue us all from the diversity of devices all over the world I guess it was a question of when rather than if.

So I have been working with javascript, or more precisely jQuery for a while now. And despite my initial scepticism, I must admit that I am somewhat convinced. The "write once, works everywhere" mantra of jQuery seems quite just, and I am able to produce stuff that I did not think was possible before. Especially when working with SharePoint UI, this has been true. While SharePoint is a great platform with endless possibilities, the UI has its limitations. Using html/jquery/css has managed to overcome many of these problems, enabling me to build wonderful, interactive stuff that delivers the wonders of SharePoint through the simplicity of html and javascript.

Ok, back to the topic: The journey has not been without challenges. JQuery can have its pitfalls, especially if you are new to the functional or asynchronous aspects of the language.

One neat feature for taking advantage of the ajax possibilities of jQuery is the use of promises. This is especially relevant if you are unable to use the .done mechanism provided by the ajax call, and you have a regular function that needs to be executed asynchronously and its result to be processed when it returns. Then you could do something like this:


function RetrieveUserByIdAsync(userId) {
var dfd = new jQuery.Deferred(); //deferred object

var siteurl = _spPageContextInfo.webServerRelativeUrl;
var executor = new SP.RequestExecutor(siteurl);

executor.executeAsync(
{
        url: siteurl +  "/_api/web/lists/GetByTitle('User')/items/GetById(" + userId + ")",
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: successHandler,
        error: errorHandler
    });
    
    function successHandler(data) {
    debugger;
var jsonObject = JSON.parse(data.body); 
var user = jsonObject.d;
dfd.resolve(user);
}

function errorHandler(data, errorCode, errorMessage) {
   alert(errorMessage); 
   dfd.reject( errorMessage );
   debugger;
}

// Return the Promise so caller can't change the Deferred
  return dfd.promise();

}


Calling the function like this:

$.when(RetrieveUserByIdAsync(id)).then(function(currentUser) {
...


This function utilizes the SharePoint REST api to asynchronously retrieve a given user. The function returns a promise, and when the resolve call is made, the "then" clause of the caller is executed, "promising" that the data will be available. This makes it possible to write much cleaner code than you would e.g. when coding all the logic in the successHandler of the async method. It enhances encapsulation and modularisation of your code and makes it easier to understand.

BUT - the whole async nature of this pattern also requires you to change your way of thinking when coding. I recently needed to write a function that would give me the current user. Easy peasy I thought, I just get the id of the current user and calls the RetrieveUserByIdAsync function. But hey - it's async, how do I solve that? Would it be possible to nest promises so that the execution sequence would lead neatly back to the caller in not just one step, but two? I had to try it. So I created an overload of my initial function:

function RetrieveCurrentUserAsync() {
var dfd = new jQuery.Deferred(); //deferred object

$.when(RetrieveUserByIdAsync(_spPageContextInfo.userId)).then(function(user) {
dfd.resolve(user);
});
// Return the Promise so caller can't change the Deferred
return dfd.promise();
}


And then called it like this:


$.when(RetrieveCurrentUserAsync()).then(function(currentUser) {
...

And voila! The first async function is calling the second, politely waiting in line until it returns before resolving which again returns the result to the top level. 

This example used two levels, but I suppose there is no theoretical limit for how many levels of nested promises you could use, although I would hardly see how you could use more than a few levels without negatively impacting the readability of your code. But in this case, a two level nesting it solved my problem very nicely!

Posted on Wednesday, November 20, 2013 4:11 PM jquery , sharepoint , REST | Back to top


Comments on this post: Nested promises...

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Thorvald Bøe | Powered by: GeeksWithBlogs.net