Skip to content

Instantly share code, notes, and snippets.

@jennceng
Last active December 7, 2016 20:28
Show Gist options
  • Save jennceng/8ee752de10db9eb9a2a455e19d3126be to your computer and use it in GitHub Desktop.
Save jennceng/8ee752de10db9eb9a2a455e19d3126be to your computer and use it in GitHub Desktop.

JS Promise API

Asynchronous Programming

  • Javascript can only execute one thing at a time, if there is a process that is time costly like communicating with a database, we have ways to handle these processes asynchronously

  • callback pattern - if we want to ensure a particular sequence of execution, traditionally one way we do this is via callbacks

  • since functions can be passed around as arguments, callbacks involve taking another funciton as an argument so that the callback is only executed after the asynchronous task/function completes

  • this works fine for simple callbacks, but if there is a series of events you need to happen you encounter callback hell , aka Pyramid of Doom aka spaghetti code


Set Timeout

  • an example of an async function that takes in a callback and a time delay as arguments

  • after the time delay elapses, the callback function is scheduled to be executed


Promises

Promise

  • native to ES6, Promises were developed to help us deal with callback hell, makes code more readable and easier to debug
// basic structure for making a new promise via Promise class
exampleFunction = () => {
 return new Promise((resolve, reject) => {
  
 }
}
// importantly what's inside the block of the promise can be an async function which is dope
new Promise((resolve, reject) => {
  // do something asynchronously

  if (/* things are successful */) {
    resolve("It worked!")  // execute .then()
  } else {
    reject(Error("It broke!"))  // execute .catch()
  }

})
  .then((result) => {
  // result is the argument from the resolve above
  // process data, add elements to the DOM, etc...
  console.log(result)

})
  .catch((err) => {
  // err is the argument from the reject above
  // show user an error message, retry network request, etc...
  console.log(err)
})

Terminology

  • Pending - he promise has not been responded to yet

  • Settled - the promise has received some response, it is either:

  • fulfilled - things went well, triggers the function in .then ( )

  • rejected - things are not dope, triggers the funciton in .catch( )

Chaining

  • one of the most powerful aspects of Promises is chaining, the ability to chain multiple .thens to guarentee execution in a predictable order

  • what’s super dope is that if any of the .thens results in an error, it will skip any other .thens and go straight to the .catch



JS Fetch API

Intro

  • in the wild you may not be generating raw Promises often, our interaction with Promises will usually be on new technology built with it such as the Fetch API
  • will become especially useful when we move to React
  • evolution from AJAX, easier for us to interact with, can also chain more easily versus .done() callback pattern in ajax

Promise and Reponse

  • Fetch API is used to fetch resources from a server and returns a promise

  • Once promise is fulfilled we are given a Response object

  • useful attributes and methods such as status, ok boolean, json() method

  • if the server response was erroneous it doesn’t automatically trigger the catch, must check the response.ok() boolean and throw an error if not okay

// typical flow of a fetch
fetch('http://localhost:4567/books.json')
  .then(response => {
    if (response.ok) {
      return response;
    } else { // if response was not okay, throw an error to trigger .catch
      let errorMessage = `${response.status} (${response.statusText})`,
          error = new Error(errorMessage);
      throw(error);
    }
  })
  .then(response => response.json())
  .then(body => {
    console.log(body);
  })
  .catch(error => console.error(`Error in fetch: ${error.message}`));

Post

  • fetch defaults to GET if no verb given
  • if back end is expecting in JSON format, make sure to JSONify before sending it
// typical post FETCH
let data = {
  book: {
    name: 'book from fetch'
  }
};
let jsonStringData = JSON.stringify(data);

fetch('http://localhost:4567/books.json', {
  method: 'post',
  body: jsonStringData
}).then(response => {
    if (response.ok) {
      return response;
    } else {
      let errorMessage = `${response.status} (${response.statusText})`,
          error = new Error(errorMessage);
      throw(error);
    }
  })
  .then(response => response.json())
  .then(body => {
    console.log(body);
  })
  .catch(error => console.error(`Error in fetch: ${error.message}`));

Fetch exercise solution

fetch('http://localhost:4567/books.json')
  .then(response => {
    if (response.ok) {
      return response;
    } else {
      let errorMessage = `${response.status} (${response.statusText})`,
          error = new Error(errorMessage);
      throw(error);
    }
  })
  .then(response => response.json())
  .then(body => {
    return(body.books)
  }).then(books => {
    books.forEach(book => {
      $("#books").append(`<li>book: ${book.name} </li>`);
    })
  })
  .catch(error => console.error(`Error in fetch: ${error.message}`));

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