It started with a Promise

Nick Farrelly
4 min readApr 5, 2021

Then we got here, finally, with no exceptions.

What is a promise?

Man with many hats on his head, while in a prayer squatting position
Here I am promising that i’ll return the hats safely

A promise is an object which will return an asynchronous (think not at the same time) result. The classic promise use case is fetching data from a remote server. You have no idea how long it’ll take for the data to come back, you’re just promising JS that it’ll come. You can then access it

new Promise( (resolve, reject) => {
// logic to resolve or reject
}.then(result => {
// logic with the result of the promise
}

Await (hehe), what if the data never comes back from the server?

Two things. Before the promise resolves or rejects its status is set to be pending. If it returns the data successfully, the status is set to be fulfilled, or rejected if the fetch failed. Secondly, you can handle that scenario using a ‘.catch’

e.g.

new Promise( (resolve, reject) => {    // ...}.then(result => {

// ...
}.catch((error) => { // logic with the error}

What’s an example of a promise in use?

Here’s a promise that after a thousand ms, will resolve.

const myPromise = new Promise((resolve, reject) => {
setTimeout( () => { resolve(‘finished’) }, 1000
}

Wait, what’s the ‘resolve’ and ‘reject’?

So when you receive a result, you then either ‘resolve’ (fulfill) or ‘reject’ (reject) the promise result. To resolve the promise is for it to be successful, whilst a rejection is for it failing. A rejection is then handled by the catch scenario described above.

When I ‘console.log’ the value ‘myPromise’, I just get this ..

[object Promise] { ... }

How can I use the result?

Well you’re actually just logging the ‘Promise’ not the result, it’s asynchronous remember? To access it’s fulfilled value, you’ll need to use a ‘.then’.

const myPromise = new Promise((resolve, reject) => {    setTimeout( () => { resolve(‘finished’) }, 1000
}.then(result => {
// you have access to the result within this scope}

What about when I need to use that result in another promise?

Let me introduce you to callback hell..

const myPromise = new Promise((resolve, reject) => {    // the initial promise resolves after 1s
setTimeout( () => { resolve('finished') }, 1000)
}).then((result) => { // we then create a second promise from the result above new Promise((res, rej) => { setTimeout( () => { res("I am glad that I have " + result)
}, 1000)
}).then(r => { // we have ended at the result of the second
// but this can go as further than your nightmares can
console.log('r:',r); })
})
console.log(myPromise)

Output (check it on JSFiddle):

[object Promise] { … }“r:”, “I am glad that I have finished”

Note that we receive an ‘[object Promise…’ because the Promise is pending, and we’re not in the correct scope to see the result. However, the console log within the Promise is in the correct scope, and can see the result.

There are legitimate scenarios where developers end up in.. callback hell. *Imagine thunder striking as those two words are read*

How can you avoid it?

Await, on this, there’s new syntax for handling a Promise. ‘Async/Await

So instead of having to wait for the result of a Promise in order to chain another, you can just wait for it, well I should say, you can ‘await’ it

const fetch = async () => await setTimeout( () => console.log(‘hello’), 1000)// equivalent tofunction async fetch() {await setTimeout(() => console.log(‘hello’), 1000)}

You can only `await` on a function which has been marked as `async`.

However, there is one prerequisite for the async/await syntax. Await can only be called within an async function. So you’re not able to just slap it’s usage in anywhere, but with that being said, with an inline function (as is in the above code snippet), it’s effectively the same as a promise.

If you remember the callback hell from before, here’s it now

const myFunc = async () => {  // the (async () => ..)() syntax invokes the func immediately
// meaning we don't need to call the func, just the result
const firstCall = (async () => 'finished')(); const secondCall = (async () => "I am glad that I have " + await firstCall)(); // we're in the correct scope, so we see the result
console.log('r:', await secondCall);
}
// we'll see the Promise object here
console.log(myFunc());

Output (JSFiddle):

[object Promise] { … }"r:", "I am glad that I have finished"

This way you can now easily `await` multiple fetches, or requests.

So we’ve learnt :

  • What a promise is, how to use them, how to access them
  • Promise statuses, then, catch
  • Callback hell
  • Async/await syntax

Is there more you want to know about Promises, or Async/Await?

What do you think about the evolution of asynchronous code in JS?

--

--

Nick Farrelly

React/React-Native developer. Passionate about learning, improving, and writing. www.thefarrelly.com