In the Atom, inside the playground folder, we'll create a new file and call it promise.js. Before we define promises and talk about exactly how they work, we will run through a simple example because that is the best way to learn just about anything—going through an example and seeing how it works.
To get started, we'll work through a very basic example. We'll stick to the core promise features.
To get started with this very simple example, we'll make a variable called somePromise. This will eventually store the promise object. We'll be calling various methods on this variable to do something with the promise. We'll set the somePromise variable equal to the return result from the constructor function for promises. We'll use the new keyword to create a new instance of a promise. Then, we'll provide the thing we want to create a new instance of, Promise, as shown here:
var somePromise = new Promise
Now this Promise function, which is indeed a function—we have to call it like one; that is, it takes one argument. This argument will be a function. We'll use an anonymous arrow function (=>), and inside it, we'll do all of the asynchronous stuff we want to do:
var somePromise = new Promise(() => {
});
It will all be abstracted, kind of like we abstract the HTTP request inside the geocodeAddress function in the geocode.js file:
const request = require('request');
var geocodeAddress = (address, callback) => {
var encodedAddress = encodeURIComponent(address);
request({
url: `https://maps.googleapis.com/maps/api/geocode/json?address=${encodedAddress}`,
json: true
}, (error, response, body) => {
if (error) {
callback('Unable to connect to Google servers.');
} else if (body.status === 'ZERO_RESULTS') {
callback('Unable to find that address.');
} else if (body.status === 'OK') {
callback(undefined, {
address: body.results[0].formatted_address,
latitude: body.results[0].geometry.location.lat,
longitude: body.results[0].geometry.location.lng
});
}
});
};
module.exports.geocodeAddress = geocodeAddress;
All of the complex logic in the geocodeAddress function does indeed need to happen, but the app.js file doesn't need to worry about it. The geocode.geocodeAddress function in the app.js file has a very simple if statement that checks whether there's an error. If there is an error, we will print a message, and if there's not, we move on. The same thing will be true with promises.
The new Promise callback function will get called with two arguments, resolve and reject:
var somePromise = new Promise((resolve, reject) => {
});
This is how we'll manage the state of our promise. When we make a promise, we're making a promise; we're saying, "Hey, I'll go off and I'll fetch that website data for you." Now this could go well, in which case, you will resolve the promise, setting its state to fulfilled. When a promise is fulfilled, it's gone out and it's done the thing you've expected it to do. This could be a database request, an HTTP request, or something else completely.
Now when you call reject, you're saying, "Hey, we tried to get that thing done man, but we just could not." So the promise has been considered rejected. These are the two states that you can set a promise to—fulfilled or rejected. Just like inside geocode.js, we either provide one argument for an error, or we provide the second argument if things went well. Instead of doing that though, promises give us two functions we can call.
Now, in order to illustrate exactly how we can use these, we'll call resolve. Once again, this is not asynchronous. We're not doing anything quite yet. So all of this will happen essentially in real time, as far as you see in Terminal. We'll call resolve with some data. In this case, I'll pass in a string, Hey. It worked!, as shown here:
var somePromise = new Promise((resolve, reject) => {
resolve('Hey. It worked!');
});
Now this string is the value the promise was fulfilled with. This is exactly what someone will get back. In case of the geocode.geocodeAddress function in app file, it could be the data, whether it's the results or the error message. In our case though, we're using resolve, so this will be the actual data the user wanted. When things go well, Hey. It worked! is what they expect.