While I tend to stay away from Promises as much as possible, there are times you simply cannot avoid them. Certain situations like using the 3rd Party APIs, or even some new built-in APIs like Fetch provide circumstances that would keep you stuck to Promise flows, and when this happens you have to follow the general abstract rules of Promise chains, make it hard to use Promises in functions. Let’s fix that:

Promise Lifting

The first way to control a promise is to learn all about Promise Lifting, or in other words the ability to write your own promises with a resolve/reject structure. Here is a quick example where we create a promise that uses another function as the point of determination for the resolve and reject.

const promiseOne = new Promise((resolve, reject) => {
  someFunction((error, data) => {
    if(error) reject(error);
    resolve(data);
  });
});

promiseOne()
.then(response => response.json())
.then(output => {
  console.log('here's our resolve!');
}).catch(error => console.error('Error:', error));

In this example we use this to run an asynchronous function, and extract the data without having to worry about other functions getting ahead of us, something extremely important when working with Node.js.

Overall this is the first step to controlling Promises. while having another method of control flow when callbacks and ES6 & ES7 asynchronous options are not available.

 

Using Promises in Functions

When using something like Fetch, or even 3rd-Party APIs, you may be left with Promises as an answer. The issue comes when you want that promise to be easily accessible, and reusable. I found this to be a common example:

First let’s look at how it is advised to accomplish this:

function callPromise(url) {
  return fetch(url);
}

callPromise()
.then(res => {
  console.log(res);
})

 

Wait, what? To me this is just added redundancy. We have called the thenable state from an object instead of calling it directly from the promise. So what is the point? We are forced to finish the promise in another block, instead of in the function itself.

If you haven’t figured this out already even with this outside thenable section you cannot return results from a promise, if you return the promise you will receive the state of the promise. What if you want the returned data to work with another function?

 

Setting Promise Data Free

For some reason the answer is easier than one would think when it comes to making promises useful in a more functional way. We only need to extract the data from the scope, and use it elsewhere. Let’s call it all in the function, extract that return value, and dry it up!

function promiseCaller (url, f) {
  return fetch(url)
  .then(res => res.json())
  .then(out => {
    f(out);
  })
  .catch(error => console.log('Error:', error));
}

promiseCaller('someurl', (output) => {
  console.log(output);
});

Sometimes we have to dig up old tricks like an original callback to make things work our way. By using this callback method we make sure that the data is returned the moment the promise is done, as well as moving that data to any block we please! This is what I call real Promise utilization, and a promise that will fit into anyone’s control flow, no matter what the abstraction.

I personally use this exact abstraction consistently for my own AWS SDK API which many will know works best with their promise structure. This same abstract allows my redux actions to call the promise functions, return the data, and send them straight to any part of the front-end. Thinking about working with the Promise layout without this ability makes my skin crawl.