Skip to content

Instantly share code, notes, and snippets.

@cklanac
Last active October 12, 2019 01:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cklanac/d9cfd7e858ad6d5afb51c456933b7f89 to your computer and use it in GitHub Desktop.
Save cklanac/d9cfd7e858ad6d5afb51c456933b7f89 to your computer and use it in GitHub Desktop.
Challenge 04: Promises

For this challenge, you'll update both the client and the server to use promises.

On the client, you will change the API methods to return promises instead accepting callbacks. Then update the api.METHOD() calls to use promises.

On the server, you will update simDb to use promises, we'll provide the code. Then update the queries to use promises instead of callbacks.

Requirements

  • Update the server-side code

    • Update the simDb.js file with "promisified" version
    • Update the DB queries to use promises
  • Update the client-side code

    • Update api.js methods to return a promise from $.ajax
    • Update client-side api calls to use promises

Update the Server

Getting Started

To get started, you need to update the simDB to use promises. Copy the Promisified simDB code to your /db/simDB.js. The new version uses Node's promisify utility to use promises instead of callbacks. Don't worry about the details, yet. We'll cover creating promises in a future challenge

Update notes.METHOD() to use promises

Your first challenge to is to convert the notes.METHOD queries from callbacks to promises. We'll help you get started by stepping thru the notes.find so you can update the others on your own. Below is an example of the callback-style function followed by the promise-style equivalent.

Callback Style

  notes.find(id, (err, item) => {
    if (err) {
      return next(err);
    }
    if (item) {
      res.json(item);
    } else {
      next();
    }
  });

Promise Style

  notes.find(id)
    .then(item => {
      if (item) {
        res.json(item);
      } else {
        next();
      }
    })
    .catch(err => {
      next(err)
    });
});

Notice, the callback is moved to the .then() and the error check condition has been extracted and moved to the .catch().

Your challenge is to update the other queries (filter, update, create and delete) to use promises. As you work thru the challenge, verify your changes using Postman.

BONUS: Update the client-side code

Currently, all the api.METHOD() functions in api.js on the client use callbacks. Your bonus challenge is to update api.js and all the functions that call the API. Thankfully, as of jQuery 3.0, the $.ajax returns a promise-like object which is fully Promises/A+ spec compliant - meaning they work the same as native Javascript Promises.

Update api.js methods to return a promise

To help you get started, we've provided a before and after example of the .search method, see below.

Before: Callback Style

  ...
  search: function (query, callback) {
    $.ajax({
      type: 'GET',
      url: '/api/notes/',
      dataType: 'json',
      data: query,
      success: callback
    });
  },
  ...

After: Promise Style

  • Remove the callback parameter
  • Remove the success property from the $.AJAX options object
  • Return the promise return $.ajax({....
  ...
  search: function (query) {
    return $.ajax({
      type: 'GET',
      url: '/api/notes/',
      dataType: 'json',
      data: query
    });
  },
  ...

Before updating the other methods, you should verify your changes in a clean, standalone environment. Continually verifying your changes before proceeeding will help you become an efficient developer. It is the developer's equivalent to the carpenter's old adage "measure twice, cut once".

In the /public folder, create a temporary HTML file named scratch.html that loads jQuery and the /scripts/api.js file Then, in <script> tags, add the following function which test the api.search method.

<script>
  // test get all
  api.search({})
    .then(response => {
      console.log(response)
    });

  // test get all with search term
  api.search({searchTerm: 'cats'})
    .then(response => {
      console.log(response)
    });
</script>

Alternatively, you could create a separate .js file with the code and load in scratch.html.

Start your server and load scratch.html in your browser and check the console in Dev Tools. You should see the results from the API calls.

Your challenge is to update the other methods (details, update, create and remove) and verify them in the scratch.html.

EXTRA BONUS: Update client-side api calls to use promises

The extra bonus challenge is to update the api.METHOD calls throughout the client-side app. The api.METHOD calls use the callback style which you need to update to use promises. We'll help you with the first one.

Hint. To find all the occurrences, search for api.. That's "a-p-i DOT". Below is a list based on the code in the recent solution branch.

  • In the index.js file, you should find api.search(). Update the call to use promises

Before: Callback style

api.search({}, response => {
  store.notes = response;
  noteful.render();
});

After: Promise style

api.search({})
  .then(response => {
    store.notes = response;
    noteful.render();
  });

Your turn!

  • In the noteful.js file you will find the following methods. Update each to use promises. Remember to check your changes in Dev Tools

    • In the handleNoteItemClick() method, update the api.details() call
    • In the handleNoteSearchSubmit() method, update the api.search() call
    • In the handleNoteFormSubmit() method, update the nested callbacks of api.update(), api.create() and api.search() to use chained .then() calls.
    • And in the handleNoteDeleteClick() method, update the nested callbacks of api.remove() and api.search() to use chained .then() calls.

If you run into issues with converting the nested callbacks to promise chains, simplify! Go back to your scratch.html file above and implement the solution in a clean, standalone environment. Once it is working, integrate it into the larger application. Below is a sample.

Solutions

You can view an example solution and compare the differences between branches

Good Luck!

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