Skip to content

Instantly share code, notes, and snippets.

@joshwyatt
Created May 11, 2017 20:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joshwyatt/6ddf4887a409eb1453b0fd6e3516366b to your computer and use it in GitHub Desktop.
Save joshwyatt/6ddf4887a409eb1453b0fd6e3516366b to your computer and use it in GitHub Desktop.
An example refactor of some callback hell code to utilize promises instead.

Organizing Multiple Asynchronous Function Calls

Using Callbacks and Continuation Passing Style

const request = require('request');

doAsyncMath('2+15', function(result) {
  doAsyncMath(`${result}*3`, function(result) {
    doAsyncMath(`${result}*10`, console.log);
  });
});

/*
 * `doAsyncMath` constructs a URL with the help of the passed in
 * `expression`. Assuming the response callback is called, the
 * result will be passed into `doSomethingWithResult`.
 */

function doAsyncMath(expression, doSomethingWithResult) {
  const URL = 'https://newton.now.sh/simplify/';

  /*
   * The anonymous function definition passed in as the 2nd argument
   * to the `request` function will be called when and if a response
   * is received back from the API request made.
   */

  request(`${URL}${expression}`, function (err, response, body) {
    let result = getResultFrom(body);

    // Here the *defintion* passed in above is *called*.
    doSomethingWithResult(result);
  });

}

function getResultFrom(body) {
  return JSON.parse(body).result;
}

Building a Promise from Scratch (verbose example)

// Before using the promise, we must create it.

let promise = new Promise(executor);

function executor(functionToResolvePromise, functionToRejectPromise) {
  let valueToResolvePromiseWith = 7;
  functionToResolvePromise(valueToResolvePromiseWith);

  let valueToRejectPromiseWith = 'epic failure';
  functionToRejectPromise(valueToRejectPromiseWith);
}

// Now that the promise has been created we can use it

promise
  .then(functionToBeGivenResolvedValue)
  .catch(functionToBeGivenRejectedValue)

function functionToBeGivenResolvedValue(resolvedValue) {
  console.log(`Here is the resolved value: ${resolvedValue}`);
}

function functionToBeGivenRejectedValue(rejectedValue) {
  console.log(`Here is the rejected value: ${rejectedValue}`);
}

Using a Hand Made Promise to Refactor Callback Hell

function doAsyncMath(expression) {
  const URL = 'https://newton.now.sh/simplify/';
  return new Promise(function(resolve, reject) {

    request(`${URL}${expression}`, function (err, response, body) {

      if(err) {
        reject(err);
      }

      let result = getResultFrom(body);
      resolve(result);
    });
  });
}

function getResultFrom(body) {
  return JSON.parse(body).result;
}

const request = require('request');
let result = doAsyncMath('2+15');

result
  .then(function(resolvedValue) {
    console.log(`InsidePromise1: ${resolvedValue}`);
    return doAsyncMath(`${resolvedValue} * 10`);
  })
  .then(function(resolvedValue) {
    console.log(`InsidePromise2: ${resolvedValue}`);
    return doAsyncMath(`${resolvedValue} * 10`);
  })
  .then(function(resolvedValue) {
    console.log(`InsidePromise3: ${resolvedValue}`);
    return doAsyncMath(`${resolvedValue} * 10`);
  })
  .then(function(resolvedValue) {
    console.log(`InsidePromise4: ${resolvedValue}`);
    return doAsyncMath(`${resolvedValue} * 10`);
  })
  .catch(function(rejectedValue) {
    console.log(`There was an error: ${rejectedValue}`);
  });

Refactoring to Use a Promise Producing Library (best)

const rp = require('request-promise');

function doAsyncMath(expression) {
  const URL = 'https://newton.now.sh/simplify/';
  return rp(`${URL}${expression}`);
}

function getResultFrom(body) {
  return JSON.parse(body).result;
}

result = doAsyncMath('2+10')
  .then(body => doAsyncMath(`${getResultFrom(body)}*10`))
  .then(body => doAsyncMath(`${getResultFrom(body)}*10`))
  .then(body => doAsyncMath(`${getResultFrom(body)}*10`))
  .catch((err) => { throw new Error(err) })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment