0

Im in situation where I have many potential error sources. Is there an elegant solution to this mess?

How should I reject it?

  function myFuction(hash) {
    return new Promise((resolve, reject) => {
      // this could return error
      const id = atob(hash);

      // this could return error   
      let data = firstFunction(id);

      // return error if not true
      if (data && data.id) {
        // this could return error   
        return secondFunction(data.id)
          .then(item => {

            // return error if not true
            if (item) {
              // this could return error  
              return thirdFunction(item)
                .then(payload => {
                  resolve('OK');
                });
            }
          });
      }
    });
  }
Solo
  • 6,687
  • 7
  • 35
  • 67
  • What do you mean by "*this could return error*"? Do they throw exceptions? – Bergi May 08 '17 at 20:36
  • `throw new Error('error text');` @Bergi – Solo May 08 '17 at 20:37
  • Check the edit to my answer – Bergi May 08 '17 at 20:44
  • I think I need to start learning ES6 Promises again, because I have no idea how or why `return Promise.resolve().then(() => { // ...` works. Thanks @Bergi – Solo May 08 '17 at 20:51
  • It gives us an immediately executed promise `then` callback context where exceptions will be implicitly caught. One could also write `try { atob(…); firstFunction(…) } catch(e) { return Promise.reject(e); }` – Bergi May 08 '17 at 20:53

1 Answers1

2

Avoid the Promise constructor antipattern! You can use early returns with Promise.reject or just throw errors:

function myFuction(hash) {
    return Promise.resolve().then(() => {
        // this could throw error
        const id = atob(hash);
        // this could throw error   
        let data = firstFunction(id);

        // return error if not true
        if (!data || !data.id)
            return Promise.reject(new Error("…")); // alternative: throw new Error("…");

        return secondFunction(data.id);
    }).then(item => {
        // return error if not true
        if (!item)
            return Promise.reject(new Error("…")); // same here

        return thirdFunction(item);
    }).then(payload => 'OK');
}

(Additionally I applied some flattening, but as long as your always return from promise callbacks you could nest as well)

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Is there a recommendation on `return Promise.reject(new Error(...))` vs. `throw new Error(...)`? I know they both give you the same outcome, but is there any reason to use one over the other? – jfriend00 May 08 '17 at 23:40
  • @jfriend00 No idea. `return Promise.reject(…)` works also outside of `then` callbacks, and is a value (can be passed around when it comes handy), while `throw` is shorter and doesn't rely on intact globals. I don't know whether exceptions have a noticeable overhead. – Bergi May 09 '17 at 00:03