Promise chaining vs async/await

Oh man, in my React/Redux final project, which uses New York City’s open data to create a dashboard for city renters, I ended up having to chain a lot of API GET requests together because of the way the data was organized.

For instance, to get a building’s Registration Info (information about building owner and manager), I had to first lookup a building’s Building Identification Number (BIN) in one dataset, cross-reference than BIN with a Registration ID in another, and use the Registration ID in a third to finally come across the Registration Info.

And all that resulted in (assume fetchBin, fetchRegId, and fetchRegInfo are the appropriate API calls:

export function getRegistrationInfo(address) {
  return dispatch => {
    dispatch({ type: 'GET_BIN', address });

    return fetchBin()
      .then(
        response => {
          dispatch({ type: 'GOT_BIN', address, response });
          dispatch({ type: 'GET_REG_ID', address });

          return fetchRegId()
        }
      )
      .then(
        response => {
          dispatch({ type: 'GOT_REG_ID', address, response });
          dispatch({ type: 'GET_REG_INFO', address });

          return fetchRegInfo()
        }
      .then(
        response => {
          dispatch({ type: 'GOT_REG_INFO , address, response});
        }
      )
  }
}

I just don’t like it. Maybe some people like chaining these Promises because it’s like a timeline or something, but I think it just looks bad!

Enter async and await. Unfortunately I didn’t know about them until my code review, but I wish I had! Introduced in ES2017, it’s a new way to handle asynchronous functions in JavaScript!

async allows you to declare a function that will return a Promise. More importantly, async functions can contain await expressions that pauses execution while the expression is resolved. Using async/await, I could refactor the above code as follows:

export async function getRegistrationInfo(address) {
  return dispatch => {
    dispatch({ type: 'GET_BIN', address });
    const binResponse = await fetchBin();
    dispatch({ type: 'GOT_BIN', address, binResponse });

    dispatch({ type: 'GET_REG_ID, address });
    const regIdResponse = await fetchRegId();
    dispatch({ type: 'GOT_REG_ID', address, regIdResponse });

    dispatch({ type: 'GET_REG_INFO, address });
    const regInfoResponse = await fetchRegInfo();
    dispatch({ type: 'GOT_REG_INFO, address, regInfoResponse });
  }
}

To me, that looks so much better and simpler. I understand there are some difficulties with error catching when using async/await, which I’ll have to look more into. And I admit that my Promise chaining did not look as neat as the example I have above, which isn’t that bad, because I hadn’t seen the proper way to do it, as detailed here. I had been indenting with every then, which was just getting crazy…

Anyway, at least it’s another option I now know about!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.