Skip to content
No description, website, or topics provided.
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
app.js
readme.md

readme.md

Callbacks & Promises

The Problem: Asynchronoous events occur after synchronoous events

const users = [];

console.log('Users starting value \n', users);
console.log(`---------------------------------------`);

setTimeout(() => {
  console.log('Adding new user');
  users.push({id: 1, name: 'John Doe'});
  console.log('New user added');
  console.log(`---------------------------------------`);
  console.log('Users after push \n', users);
  console.log(`---------------------------------------`);
}, 2000);

console.log('New Users Last Check \n', users);
console.log(`---------------------------------------`);

One way we can solve this problem is by using a callback to control the execution order of our code

console.log('Users starting value \n', users);
console.log(`---------------------------------------`);

const addUser = (user, callback) => {
  setTimeout(() => {
    console.log('Adding new user');
    users.push(user);
    console.log('New user added');
    console.log(`---------------------------------------`);
    console.log('Users after push \n', users);
    console.log(`---------------------------------------`);
    callback();
  }, 2000);
}

addUser({id: 1, name: 'John Doe'}, () => {
  console.log('New Users Last Check \n', users);
  console.log(`---------------------------------------`);
});

But this solution quickly becomes messy as we add more API calls. Each API call must be nested inside the previous call, creating what is known as "callback hell."

Promises were introduced as a cleaner syntax.

Let's create a function that will mimick the behavoir of AJAX.

function customAjax(url, configObj) {
  console.log('Calling API...');
  const { method, headers, data, success, error } = configObj;
  const database = [];

  return new Promise((resolve, reject) => {
    if (typeof data !== 'object' || Array.isArray(data)) {
      if (error) return error(new TypeError('Data must be an object'));
      reject(new TypeError('Data must be an object'));
    } else if (!data) {
      if (error) return error(new ReferenceError('Data is undefined'));
      reject(new ReferenceError('Data is undefined'));
    }

    setTimeout(() => {
      const randomNum = Math.floor((Math.random() * 10000) + 1) // 1-1000
      data.id = randomNum * randomNum;
      database.push(data);
      if (success) return success(data);
      resolve(data);
    }, 3000);
  });
}

We can use the function above with either a callback or a promise. Let's start with the callback:

const newUser = {
  name: 'John Doe',
  email: 'jdoe@gmail.com',
};

customAjax('http://someapi.com/users', {
  method: 'POST',
  headers: {},
  data: newUser,
  success: (savedUser) => {
    console.log('Success', savedUser);
  },
  error: (err) => {
    console.log(err);
  }
});

Our callback function is being passed as the "success" property on the configuration object.

Now let's try the promise syntax:

customAjax('http://someapi.com/users', {
  method: 'GET',
  headers: {},
  data: newUser,
})
  .then((res) => console.log(res))
  .then(() => console.log('All Done'))
  .then(() => console.log('Make another api call'))
  .then(() => {
    customAjax('',{data: newUser})
      .then((res) => console.log('Second Response Result\n', res))
  })
  .catch((err) => console.log(err));


console.log('Users before createUser \n', users);

Prmosises were defitely an improvement on callbacks, but they can still git a little messy. To clean things up a bit more, the Asyn/Await syntax was introduced.

Lets make another call to our fake API, this time using the Async/Await syntax:

const createUser = async (user) => {
  try {
    const savedUser = await customAjax('http://someapi.com/users', {
      method: 'GET',
      headers: {},
      data: newUser,
      });
    
    console.log(savedUser);
    users.push(savedUser);
    console.log('Part 2')
    const savedUser2 = await customAjax('http://someapi.com/users', {
      method: 'GET',
      headers: {},
      data: newUser,
      });
    
    console.log(savedUser2);
    users.push(savedUser2);
  } catch (error) {
    console.log('In the Error block \n', error);
  }
};

createUser(newUser);

console.log('Users after createUser \n', users);
You can’t perform that action at this time.