3

I would like to create a function that returns a promise and if something throws an error within, it returns promise reject.

function promiseFunc(options) {
  return new Promise(() => {
    return options;
  });
}

function myfunc(options) {
  return new Promise(() => {
    if (!options) throw new Error("missing options");

    return promiseFunc(options).then((result) => {
      if (result.throwerr) throw new Error("thrown on purpose");

      return result.value;
    });
  });
};

My test as follows:

const myfunc = require("./myfunc");

describe('myfunc', () => {
  it('should fail without options', () => {
    return myfunc()
      .then((result) => { throw new Error(result) }, (err) => {
        console.log("test #1 result:", err.message === "missing options");
      });
  });

  it('should fail on options.throwerr', () => {
    return myfunc({throwerr: true})
      .then((result) => {}, (err) => {
        console.log("test #2 result:", err.message === "thrown on purpose");
      });
  });

  it('should return options.value', () => {
    return myfunc({value: "some result", throwerr: false})
      .then((result) => {
        console.log("test #3 result:", result === "some result");
      }, (err) => {});
  });
});

The first test pass, but the second and third fails.

Log #2 does not even run, so I assumed the "throw on purpose" messes up something, therefore I created test #3, where I don't throw anything, but it still fails. What am I missing?

Solution:

function promiseFunc(options) {
  return new Promise(resolve => {
    return resolve(options);
  });
}

function myfunc(options) {
  return new Promise((resolve, reject) => {
    if (!options) throw new Error("missing options");

    return promiseFunc(options).then(result => {
      if (result.throwerr) throw new Error("thrown on purpose");

      return resolve(result.value);
    }).catch(err => {
      return reject(err);
    });
  });
};
  • Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Apr 15 '16 at 17:44

3 Answers3

1

You forgot to pass a function with resolve and reject parameters, so your promises just don't work.

function promiseFunc(options) {
  return new Promise(resolve => { // resolve function
    resolve(options)
  })
}

module.exports = function myfunc(options) {
  return new Promise((resolve, reject) => { // since you may either resolve your promise or reject it, you need two params
    if (!options) {
      return reject(new Error("missing options"))
    }

    return promiseFunc(options).then(result => {
      if (result.throwerr) {
        return reject(new Error("thrown on purpose"))
      }
      resolve(result.value)
    })
  })
}

... and the test (mocha)

const assert = require('assert'),
      myfunc = require("./myfunc")

describe('myfunc', () => {
  it('should fail without options', done => { // mind the callback, promises are always async
    myfunc()
      .catch(err => {
        assert(err.message === "missing options")
        done() // <- called here
      })
  })

   it('should fail on options.throwerr', done => {
      myfunc({throwerr: true})
         .catch(err => {
            assert(err.message === "thrown on purpose")
            done()
      })
   })

  it('should return options.value', done => {
    return myfunc({value: "some result", throwerr: false})
      .then(result => {
          assert(result === "some result")
          done()
       })
    })
 })
Kuba Kutiak
  • 92
  • 1
  • 3
  • Yes, it works, but what if something throws an error in myfunc before it returns a resolve/reject? Btw mocha doc says that you don't need the done callback if you return a promise. – user2252655 Apr 15 '16 at 17:11
  • In myfunc the first throw is fine, only the nested throw messes up the tests. – user2252655 Apr 15 '16 at 17:18
  • Didn't know about mocha - thanks. About promises - they automatically catch all uncaught errors inside the promise body. However, it's better to use reject callback instead of throwing an error. Think of it as of a control structure, where you can perform one of two actions - fulfill the promise, or reject it, if something's wrong (eg options are undefined) – Kuba Kutiak Apr 15 '16 at 17:31
  • Thank you for pointing out the missing promise parameters. With slight modifications I managed to make it work. – user2252655 Apr 15 '16 at 17:31
0

I would like to create a function that returns a promise and if something throws an error within, it returns promise reject.

This will do it ...

var q = require('q'); // In recent versions of node q is available by default and this line is not required

function iReturnAPromise(num) {

    var def = q.defer();

    if (typeof num=== 'number') {

        try {
            var value = 100 / num;
            def.resolve(value);
        } catch(e) {
            def.reject("oops a division error - maybe you divided by zero");
        }
    } else {
        def.reject("o no its not a number");
    }
    return def.promise;
}

PS this function was coded freehand and has not been tested - but this will work. Obviously try catch should be used sparingly.

PS I prefer the q library implementation of promise instead of the default node promise library - they take a very different approach. q dispenses with all the wrapping!

danday74
  • 52,471
  • 49
  • 232
  • 283
  • Is it possible to do it with the native Promise? – user2252655 Apr 15 '16 at 16:36
  • yes very possible using the same logic with different syntax! i havent used the native promise lib for a while, i prefer q so cant code it without looking it up, i will leave that to you :) – danday74 Apr 15 '16 at 16:37
  • Thank you! I would like to exclude any external libraries, so I guess I have to keep bugging on it :) – user2252655 Apr 15 '16 at 16:45
  • q is not an external library in recent versions of node - its built in and available by default without requiring it - depends what version of node you are using – danday74 Apr 15 '16 at 16:46
  • Oh, I did not know that. I'm using 5.6 currently, but It's about time to update it. Thank you again! – user2252655 Apr 15 '16 at 16:50
  • you seem like a nice guy - coded it for you i couldnt resist lol - God bless – danday74 Apr 15 '16 at 17:03
0

using the promise library u wanted ...

function iReturnAPromise(num) {


return new Promise(function(resolve, reject) {


    if (typeof num === 'number') {

        try {
            var value = 100 / num;
            resolve(value);
        } catch (e) {
            reject("oops a division error - maybe you divided by zero");
        }
    } else {
        reject("o no its not a number");
    }

})

}

iReturnAPromise(7).then(
    function(response) {console.log("success", response)},
    function(response) {console.log("failure", response)}
);

// Unexpectedly this is not an error in node 5.6 because div by 0 is not an error operation anymore!
iReturnAPromise(0).then(
    function(response) {console.log("success", response)},
    function(response) {console.log("failure", response)}
);

iReturnAPromise("fred").then(
    function(response) {console.log("success", response)},
    function(response) {console.log("failure", response)}
);

you can see why i prefer the q syntax :)

danday74
  • 52,471
  • 49
  • 232
  • 283