Skip to content

Instantly share code, notes, and snippets.

@davidbecker6081
Forked from robbiejaeger/promise-pledges.md
Created September 28, 2017 19:43
Show Gist options
  • Save davidbecker6081/101bcc77857d833aec672160ad009437 to your computer and use it in GitHub Desktop.
Save davidbecker6081/101bcc77857d833aec672160ad009437 to your computer and use it in GitHub Desktop.

Writing and Working With Promises

For this assignment, you'll be reintroduced to Promises and then write your own!

Some Background

Asynchronous code is everywhere in JavaScript, and Promises are a tool that enable us to work with asynchronous code in a manageable way. You've probably consumes promises before, most likely when you used the fetch API, but how are they working under the hood. With fetch, you most likely used something like this for a GET request:

fetch('http://www.some-api/users')  
  .then(function(response) {  
    console.log('Request successful:', response);
  })
  .catch(function(error) {
    console.error('Request failed:', error)
  });

Fetch makes a request to the URL http://www.some-api/users. If fetch gets a successful response from the server, then the .then() is triggered, and the response is logged to the console (the happy path). If something goes wrong with the request, then the .catch() is triggered, and the error is logged to the console (the sad path).

As soon as fetch(url) is run, it creates a Promise object, our code can do other things while we wait for the response, and then when we get a response the promise resolves. The moment the promise resolves successfully, the then() function is called.

Simulating Asynchronicity

JavaScript has a function in the broswer called setTimeout() that takes two arguments: a callback function and a delay time. For instance, we have two lines of code here that we would normally think would run line-by-line.

setTimeout(function(){console.log("Finished")}, 1000)
console.log("Second?")

At first glance, we might think that the console would log:

-> "Finished"
-> "Second?"

But really, if you run the code in the console, the output is:

-> "Second?"
-> "Finished"

When you run the code in the console, you can see the delay that setTimeout() created. When setTimeout() runs, it allows other code to run while the timer is waiting, in this case for 1000 milliseconds. So setTimeout() is basically saying, "While I'm waiting to run some code in 1000 milliseconds, go ahead and run the next lines of code in the meantime until I'm done waiting."

Callback Approach

Say, for instance, that you want to make a function that tests the value of a number passed in as an argument...and you want to use callbacks to do something based on result. Here is what the code could look like:

function testNum(num, lessThan, greaterThan) {
  if (num < 10) {
    lessThan("less than 10")
  } else {
    greaterThan("greater than 10")
  }
}

Running the code would look like:

testNum(2, 
  (result) => {console.log(result)}, 
  (result) => {console.log(result)}
)

// "less than 10"

This example is fairly straightforward because the code is running synchronously. What if we were making a request to a website? We don't know when we would get a response back exactly, so how would we know when to run the next step in the function? I supposed you could use setTimeout() in the browser to wait an arbitrary amount of time to wait for the response, but you could be wasting time unnecessarily.

Callbacks can be great, and we use them all the time, but what could make callbacks frustrating?

If you wanted to chain two or three actions together: after the first action is completed, the second action uses the result and runs, then the third action runs based on the result of the second action. You would end up with a bunch of nested callbacks, which is commonly known as "callback hell." There are ways to reduce the complexity of callbacks, but Promises are a good solution to improve readability and usability.

Promise Approach: On Your Own

So fetch has Promises built in to it. We can actually make our own functions that use Promises! Read through this article that explains how to build functions with Promises from scratch:

https://davidwalsh.name/promises

Go through the article section by section, and write the code examples in the console as you read through each of them. The Promise pattern can be a little confusing at first, so it's important to build some muscle memory.

Exercises

These exercises are a bit contrived because you could write these functions synchronously (and you should in real life), but we're just using Promises to practice writing then from scratch.

1. Write a function testNum that takes a number as an argument and returns a Promise that tests if the value is less than or greater than the value 10.

You want to end up with a function that you can run like this (happy path):

testNum(15)
  .then((result) => console.log(result))
  .catch((error) => console.log(error))

// 15 is greater than 10, success!

And then the sad path:

testNum(5)
  .then((result) => console.log(result))
  .catch((error) => console.log(error))

// 5 is less than 10, error!

2. Write two functions that use Promises that you can chain! The first function, makeAllCaps(), will take in an array of words and capitalize them, and then the second function, sortWords(), will sort the words in alphabetical order. If the array contains anything but strings, it should throw an error.

After you make the functions with Promises, the happy path code looks like:

makeAllCaps(['wowow', 'pants', 'bird'])
  .then(sortWords)
  .then((result) => console.log(result))
  .catch((error) => console.log(error))
  
// ['BIRD', 'PANTS', 'WOWOW']

And the sad path should be:

makeAllCaps(['wowow', 5, 'bird'])
  .then(sortWords)
  .then((result) => console.log(result))
  .catch((error) => console.log(error))
  
// 'No, the array you passed in contained an element that was not a string!'

Questions

  • What is .then() used for, and what is .catch() used for?
  • What are good use cases for Promises?
  • What other libraries/functions can you find that uses Promises?

Additional Reading (not mandatory, but interesting)

How is javascript asynchronous AND single threaded?

Fun with promises in JavaScript

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment