Returning A Promise From A JavaScript Function Is Useful
Tags: javascript, wordpress, react
Published: 2020-01-07 22:03:52



One JavaScript feature that has tripped me up a bit recently is the difference between a function that returns a promise and a function that returns the value of that the promise resolves. Decoupling data fetching helps with server-side rendered apps and can also make mocking a remote API in tests easier. In my case, I wanted to use the same functions for getting data into a static file generator as I used in the React client.

In the past, I always wanted to return the result of the API call. The more that I understand the subtle difference between returning a promise and returning the result of the the promise, the more I prefer to return a promise. In this post, I will show to return a promise from an asynchronous function, with and without explicitly creating a Promise object with the new keyword. More importantly, I'll cover when and why this pattern is useful when working with remote APIs.

This is a quick post and I assume you are somewhat familiar with using async and await in JavaScript. I wrote in more detail about that [here](https://joshpress.net/two-rules-of-javascript-async-await/).


## What Is A Promise?


If you are not familiar with promises, I recommend reading [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) first. A useful definition for this article, would be to say it's a function that promises to do something and **then** let's you do something with it.


The kinds of functions we're talking about are considered "thenable". We are able to call the function "then()" on there results.

Fetch is an example of a "thenable". This example makes a remote HTTP request and then console.logs the response.

```js
fetch(url).then(r => console.log(r) )
```

## Returning A Promise From A Function


There are a few ways to return a promise from a function. One way is to use an async closure that returns a thenable function. This example gets a page of posts from a WordPress site:

```js

function async fetchPosts(page = 1){
    // Await fetch of posts
    const posts = await fetch( `https://site.com/wp-json/wp/v2/posts?page=${page}` )
    // Return posts
    return posts;
}
```

We can add a promise chain in this closure for repetitive logic. For example, parseing the response from JSON to an object:

```js

function async fetchPosts(page = 1){
    // Get posts
    const posts = await fetch( `https://site.com/wp-json/wp/v2/posts?page=${page}` )
    //Then parse
    .then( r => r.json() );
    // Then return object
    return posts;
}
```

This example is probably more useful then the first one. This pattern is useful when we want to consume this function in a closure that can **not** be async. For example:

```jsx
React.useEffect( () => {
    //Fetch posts, THEN update state
    fetchPosts(page).then(posts => setPosts(posts) );
},[page]);
```

Keep in mind, this is a function that returns a promise to make an API request. Not a function that makes an API request. That means that calling `then()` triggers the request. Another way to do it is to use `Promise.all()`

```js
//Get page 1 and page 2 of posts:
Promise.all([ fetchPosts(1), fetchPosts(2) ] ).then( posts  => {
  const page1 = posts[0];
  const page2 = posts[1];
});
```

## Using The Promise Constructor Inside An Async Closure

The other way to return a promise from a function is to instantiate a promise object, and return it. This lets us manually call the resolve and reject functions.

We can use this to add a caching layer to our `fetchPosts()` function. The function can resolve immediately, if the page of posts is in the cache:

```js
let cache = {};
function async fetchPosts(page = 1){
   return new Promise( asnyc (resolve, reject) => {
       //Is post in cache?
       if (cache.hasOwnProperty( page) ){
           //Resolve from cache right away
           resolve( cache.page );
       } 
       //Make request
       const posts = await fetch( `https://site.com/wp-json/wp/v2/posts?page=${page}` ).then( r => r.json() );
       //cache for next call.
       cache[ page ] = posts;
       //now resolve
       resolve( posts );
   });
});
   
```

## I Promise This Is Useful

In this post, I showed how to return a promise from an asynchronous JavaScript function. 

I find this to be a useful pattern when abstracting API calls from UI or other business logic. What I like is that it leaves the responsibility of **when** to call the function to the module consuming it.


*Featured Image: Photo by [Agnes Gospodinova](https://unsplash.com/@senga1?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on Unsplash*