Story:
Speaking of Promises / A + , what is the right way to reject a promise - throw an error? But if I miss catch , my application will explode!
How to use promisify and what are its advantages (you may need to read a longer version)?
Is .then(success, fail) really anti-pattern and should I always use .then(success).catch(error) ?
A longer version, described as a real life problem (I would like someone to read):
I have a library that uses Bluebird (A + Promise implementation library) to retrieve data from a database (speaking of Sequelize ). Each query returns a result, but sometimes it is empty (tried to select something, but it wasn’t). A promise is included in the result function because there is no reason for the error (having no results, this is not an error). Example:
Entity.find(1).then(function(result) { // always ending here, despite result is {} }).catch(function(error) { // never ends here });
I want to wrap this up and check if the result is empty (I can't check it everywhere in my code). I have done this:
function findFirst() { return Entity.find(1).then(function(result) { if (result) { // add proper checks if needed return result; // will invoke the success function } else { // I WANT TO INVOKE THE ERROR, HOW?! :) } }).catch(function(error) { // never ends here }); } findFirst().then(function(result) { // I HAVE a result }).catch(function(error) { // ERROR function - there either sql error OR there is no result! });
If you are still with me - I hope you understand what happened. I want to somehow run the error function (where is the "ERROR function"). The fact is that I do not know how to do this. I tried these things:
this.reject('reason'); // doesn't work, this is not a promise, Sequelize related return new Error('reason'); // calls success function, with error argument return false; // calls success function with false argument throw new Error('reason'); // works, but if .catch is missing => BLOW!
As you can see from my comments (and by spec), throwing an error works well. But there is a big one , but - if I skipped the .catch instruction, the whole application will explode.
Why don't I want this? Let's say I want to increase the counter in my database. I don't care about the result - I'm just making an HTTP request. Therefore, I can call incrementInDB() , which has the ability to return results (even for testing reasons), so there is a throw new Error if it did not work. But since I don’t need an answer, sometimes I won’t add the .catch operator , right? But now - if I fail (by appointment or fault) - I end up with your node application down.
I do not find it very pleasant . Is there a better way to work, or do I just need to deal with it?
My friend helped me, and I used a new promise to rectify the situation, for example:
function findFirst() { var deferred = new Promise.pending(); // doesnt' matter if it Bluebird or Q, just defer Entity.find(1).then(function(result) { if (result) { // add proper checks if needed deferred.resolve(result); } else { deferred.reject('no result'); } }).catch(function(error) { deferred.reject('mysql error'); ); return deferred.promise; // return a promise, no matter of framework }
It works like a charm! But I realized: Promise Anti Patterns is a wiki article written by Petka Antonov, creator of Bluebird (A + implementation). He clearly said that this was not true .
So my second question is this? If so, why? And what's the best way?
Thanks so much for reading this, I hope someone takes the time to answer it for me :) I have to add that I did not want to depend too much on frameworks, so Sequelize and Bluebird are just the things that I ended up working with. My problem is Promises as a global, not a specific framework.