Using Promises in Salesforce Lightning

Sharing is Caring

It’s no secret that Salesforce Lightning is changing the way we develop for Salesforce. At Dreamforce 2014, Salesforce introduced Salesforce Lightning and it is proving to change a lot of things we do on the platform and I’m sure it will make things a lot better for users in the long term. If you aren’t already familiar with Salesforce Lightning then you need to read my post called What is Salesforce Lightning.

Before we begin Using Promises in Salesforce Lightning, it’s vital that you understand JavaScript. I put together a list of five resources I recommend for Learning JavaScript that I strong recommend you checkout before continuing through the rest of this post.

I strongly recommend having a really good understanding of JavaScript before beginning to write JavaScript controllers in lightning.

What are Promises?

In JavaScript, everything is asynchronous or nonblocking which can make programming quite a bit more difficult and lead to very subtle but hard to debug errors. Promises simplify code by handling the success or failure of asynchronous calls and allowing operations to be chained together.

For the most part, promises are usually used for callouts to get data or do an operation on data (CRUD, etc) or do some other operation through apex or the Force.com platform.

Promises have three different states that they can go through:

  • pending – hasn’t received a response of sucess (fufilled) or failure (rejected) yet.
  • fufilled – operation completed successfully
  • rejected – an exception / failure has occurred.

Promises take a callback function as their only parameter which takes two parameters that must be functions. The two functions that are taken as parameters will be executed based on whether the promise has been fufilled or rejected. In regular JavaScript a promise usually looks something like this:

var p = new Promise(function(resolve, reject) {
	if (successfulOperation) {
		resolve(someData);
	} else {
		reject(Error('some error message'));
	}
}

So far so good? We then need to do something with the promise when it’s resolved or rejected which is done using the then() function and making sure we catch if the promise is rejected. So, this can be done like so:


p.then(function (data) {
	// do something with the data
}).catch(function (err) {
	// handle any errors
})

If you’re still confused, SitePoint has a really good article about promises which covers callback hell which ensues when lots of things need to happen.

How Promises Work in Lightning

Lightning Experience has a built in polyfill so ES6 Promises can be used without having to import an external library. If you don’t want to you, an use callbacks in JavaScript and completely ignore promises all together.

Promises execute in a microtask which means it falls out of lightning context so we need to make sure we call $A.getCallback() and $A.enqueueAction() which actually does the call out.

In your helper file, I strongly recommend creating a relatively simple function that looks something like this so you don’t need to build promises all over the place.

({
	// really simple function that can be used in every component's helper file to make using promises easier.
	executeAction: function (cmp, action) {
		return new Promise(function (resolve, reject) {
			action.setCallback(this, function (response) {
				if (response.getState() === 'SUCCESS') {
					resolve(response.getReturnValue());
				} else if (response.getState() === 'ERROR') {
					reject(response.getError());
				})
			});
		});
		
		// if an action isn't getting called you probably missed this line
		$A.enqueueAction(action);
	});
})

To take advantage of our helper method we basically just need to pass in the component and the action we want to execute, and then we can use the .then() syntax to use the results.

var someAction = cmp.get('c.getSomeAction');

var p = helper.executeAction(cmp, someAction);

// use the promise to do something :)
p.then(function (response) {
	console.log(response);
}).catch(function (err) {
	// code to handle an error.
})

As you can see with promises, it can be a lot more clear what’s happening and debugging the code. As you may have noticed, I have been blogging a lot about Salesforce Lightning and plan to have a blog post where I build a complete example in the next few weeks.

Note: Storable actions can be called a few times and shouldn’t be used with promises.

Sharing is Caring

Brian is a software architect and technology leader living in Niagara Falls with 13+ years of development experience. He is passionate about automation, business process re-engineering, and building a better tomorrow.

Brian is a proud father of four: two boys, and two girls and has been happily married to Crystal for more than ten years. From time to time, Brian may post about his faith, his family, and definitely about technology.