When Matt Mullenweg told everyone to learn JavaScript, deeply, the community went crazy trying to decipher what this means for WordPress. What should you learn? Should it be a framework, a library, or just vanilla JavaScript?
By now if you have been inclined to pick up anything, you are ready to go deeper. Even if you just start out learning a simple library like jQuery, once you get past the basic animations and fades, you will want to learn more.
A few years ago, Promises were natively added to JavaScript. Before we get into Promises, let me first explain the need or issue they address.
Ajax And Asynchronous Code
If you are going to learn anything with JavaScript, specifically with the REST API, it is how to get the data from your site using JavaScript and display it without reloading the page. AJAX was first introduced to most people with Facebook — it allows you to see your wall update without having to hit refresh. To learn more about AJAX, check out some of the other articles on torquemag.io.
Here comes the problem.
var posts = {}; $.ajax({ url: ajaxURL + '/posts', method: 'GET', success: function( res ){ posts = res; } }); $.each( posts, function( key, value ){ $( '#your-wrapper' ).append( '<h2>' + value.title.rendered + '</h2>' ); });
In the aforementioned code, I used jQuery and the REST API to grab my latest posts using the /posts endpoint and save the response from the server as var posts. I immediately want to use the response to display my posts on the page. If you were to run this code, however, you would get an error that indicates that the post isn’t defined, or rather, that it’s empty. What is more infuriating is that sometimes this code will work just fine and other times it won’t. This is the definition of a race condition or where sometimes you load the page and posts is defined, and all works, and sometimes it isn’t since the AJAX hasn’t completed yet.
Use The Success Callback
If I just want to grab the latest posts and display them, I’d do something more like this:
$.ajax({ url: ajaxURL + '/posts', method: 'GET', success: function( res ){ $.each( res, function( key, value ){ $( '#your-wrapper' ).append( '<h2>' + value.title.rendered + '</h2>' ); }); } });
Do you see the difference? When the server responds with the data, jQuery knows that the API call was a success, then runs another function which passes in the response data.
In its most simple form, this is an example of a promise. Technically, it’s async or running code based on data and events. The success function won’t run until the server says there’s a successful connection.
JavaScript Is Single Threaded
JavaScript is single threaded, meaning that it can only handle doing one thing at a time. Some languages are multi threaded, meaning that they can multitask or do multiple things simultaneously. JavaScript can’t. In the past, this was combatted with event-driven JavaScript. You fire an event, and you have an event listener waiting for that event to fire to run more code. Just like the success function above, event listeners don’t run until told to by the event that’s being fired.
jQuery ‘On’
On a side note, if you are confused about events. Look up the jQuery “on” function. You may have already used it, like this:
$('.some-element').on('click', function(){ // do something });
This is a simple click command, onclick, do something. The event is “click” and the callback function runs only when that event is fired.
Promises Solves All The Things
Event-driven JavaScript can be tedious, and while the success function works for AJAX, you have to consider scenarios where you are stringing AJAX commands together. For example say you are using the WordPress REST API to get a user’s data, and then want to string that together with a donation using the GIVE plugin API. Using nothing but the success callback function can quickly make your code long and hard to maintain.
Resolve, Reject
To make explaining this a little easier, I’m going to use a jQuery library called RSVP.js — there are a few other ones out there, but I find this code syntax one of the easiest to understand.
First, let’s get our terminology down. A Promise can have the following statuses:
Resolved – Success
Rejected – Failure / Error
Pending – Still working
Settled – Finished and either settled or rejected
When creating a promise to use, we use the resolve and reject functions to define the status.
Resolve
Resolve is the same as that AJAX success function. If you take the same AJAX call but make it a promise, we would, on success, have it resolve with the data. If the AJAX call fails or you receive an error, then you can pass the data through reject.
Reject
Reject is the error event, so if an error came up instead of a success this would return instead.
And Then
Once you have defined a promise, you would use ‘then,’ a stringed function, to continue doing your code.
https://gist.github.com/royboy789/f039bcff55559161b97b
The then function handles both resolved and rejected scenarios and allows you to continue your functions once data has been retrieved.
Stringing ‘Thens’ together to make more magic awesomeness
This is where promises improve. If you want to manipulate the data or do another AJAX call, you can do so by returning the data to the ‘then.’ You can string the functions together and they will only run continuously as they succeed. Maybe your flow looks something like this:
- Get latest posts
- Cycle through each to grab ID
- Do another AJAX call to another API to get more data (i.e a payment)
- Do another AJAX call (i.e update post with payment details)
- Create new objects for each post with merged data
- Display post object(s)
This can get tricky if you are using jQuery AJAX alone, but with promises, you can simply keep on returning. And the best thing is it won’t keep running when there is a failure. This enables you to catch failures quickly and diagnose why they are failing. In the aforementioned example, if a payment doesn’t go through, you may want to halt the operation and notify them.
AngularJS $q
It is no secret that I love AngularJS and what it can do. One of my favorite things about it is that it has promises baked in with $q. You can create a deferred object which utilizes promises to add complexity to your app.
In addition, many of the other built in AngularJS functionality is promise-based. This includes $http which is the default AJAX wrapper for Angularjs, which allows you to work with promises out of the box without much extra code needed.
More Reading
I have only skimmed the surface of promises in JavaScript. Feel free to leave comments with other things you love about Promises, or how you are using them in WordPress.
Note: The article JavaScript Promises on html5ocks.com by Jake Archibald provides a great introduction to the topic. It’s written in easy-to-understand language. He goes into further detail about Promises, and talks about why they are useful and further things you can do with them.
No Comments