Using Javascript promises within Lightning Components

My new project requires a lot of javascript coding for Lightning component. Many books and guides about programming will teach you jsut a basics but all it seems like this picture

754a1def902e9d60cbd631184106d883

Author will give you a very basic example of use and leaves you alone. Lightning Components developer guide does it. Actually when they teaching about using asynchronous javascript in Lightning they shows how to use action.setCallback for just one server action is you callback stack. But what should you do if you need to call server action, then analyse the response and based on this response to make another server callout or few? Probably you can write a some callBack Hell code.

promises-and-chaining-in-angularjs-into-callback-hell-and-back-again-17-638

Something like that

[code lang=”js”]

var action = cmp.get("c.serverAction"); action.setCallback(this, function(response){ var state = response.getResponse(); if (state === "SUCCESS") { if (response.getReturnValue() === someCheckedValue) { var action2 = cmp.get("c.serverAction2"); action2.setCallback(this, function(response2) { var state2 = response2.getResponse(); if (state2 === "SUCCESS") { if (someCondition) { var action3 = cmp.get("c.serverAction3"); action3.setCallback(this, function(response2) { // you can check how deep the rabbit hole goes by adding a few callbacks }}}}}}}); [/code]

I pretty sure that you found that such code will not be maintainable and flexible as you want. Actually when you add some business logic and error handling within these function you will find that you stack of callbacks takes a 150-200 LoC. Not so good.

Here’s a option of using JavaScript promises. (David Walsh’s post)

[code lang=”javascript”]

// CONTROLLER ——– var someFunc = function() { // runAsync is a function which returns Promise runAsync().then( function(response) {//onSuccess if (response["status"] === 1) { helper.callServerAction2(cmp); } else if (response["status"] === 2) { helper.callServerAction3(cmp); } else if (response["status"] === 3) { helper.callServerAction4(cmp); helper.callServerAction5(cmp); } }, function(error) { //onError console.error("Failed!", error); }); }

// HELPER ——–

var runAsync = function(cmp) { var action = cmp.get("c.serverAction"); // here’s a first trick – you need to call another helper method through this // but in context of Promise ‘this’ will be different var ltg = this; return new Promise(function(resolve, reject){ // do some Asynchronous action here action.setCallback(ltg, function(response) { var state = response.getState(); ltg.callSomeHelpeMethodFromPromise(); if (state === "SUCCESS") { resolve(action.getReturnValue()); } else { reject(state); } }); }); } [/code]

So, as you can see from the code above using of Promises makes your code much modular and flexible to change. This’s a reason why you need to use Promises in your code. If you using jQuery in your project you can see to jQuery Deferred Objects which does the same but have a little bit easy API.

Thanks for reading

[javascript][lightning][lightning components][promises][salesforce]