Search code examples
javascriptasync-awaittry-catches6-promisefetch-api

Remove indentations in a tree of promises


I want to remove indentations in a javascript funtion that inside has a variable that recive the value of a promise. Inside of it has a try-catch with some code and inside the try section has a fetch with his own then and catch.

My question is, how can I simplify the code, even creating new functions if needed, to reduce the amount of indentations.

Thanks for advance.

Here an example code:

function getData(url) {
  const myVariable = new Promise((resolve, reject) => {
    try {
      fetch(url)
        .then((resp) => resp.json())
        .then(json) => {
          //some code here
        });
        // more code here
        resolve();
      })
      .catch(() => { // this catch is of the fetch
        // more code here
        resolve();
      });
    } catch (error) {
      // more code here
      reject();
    }
  });
}

Y tried to transform the fetch using the ES6 async-await but I can not use an async funtion inside a promise


Solution

  • You don't need a new Promise. Once you have a promise -- like returned by fetch() -- you don't need another promise to tell you when the first one resolves. The same is true when you have a promise coming from then() calls: you don't need an extra promise for them. It is an antipattern to use the promise constructor callback just to create another promise (using some API).

    Your example code has syntax issues (there are more closing braces than opening), so the .catch() method is not called on a promise. Your comment suggests you want to call it on the promise returned by fetch, but then it should be chained before the first then call. Each then() returns a new promise, and maybe you wanted to chain .catch() on the last .then(). In that case it will catch rejections of any of the previously chained promises, which means the outer try/catch block is not going to ever execute the catch block -- there is nothing remaining that can cause a run time error.

    Another issue with the code (once its syntax errors are fixed) is that although myVariable will be assigned a promise:

    • That promise will resolve to undefined
    • The getData function will return a promise that will resolve to undefined

    That is not very useful. You should resolve that promise with the data you got from the json() promise.

    You can use async await like so:

    async function getData(url) {
      try {
        const resp = await fetch(url);
      } catch(err) {
        console.log("fetch failed with following error", err);
        throw err; // rethrow so caller's promise gets rejected
      }
      try {
        const data = await resp.json();
      } catch(err) {
        console.log("json() failed with following error", err);
        throw err; // rethrow so caller's promise gets rejected
      }
      return data;
    }
    

    As in this example the error handling is nothing more than just reporting on errors and then bubble the error upwards, it would make sense that the caller would take the responsibility to report on errors:

    function getData(url) {
        fetch(url).then(resp => resp.json());
    }