1

It's being hard to learn how to avoid the deferred antipatern with the info I could find. I'm using Q library for Nodejs.

As it is possible to read, basically, we've to try to do not reject or answer to a promise with deferred.reject or deferred.resolve.

deferred.resolve must be replaced by a return sentence, so that point is quite simple.

The problem comes when I want use a promise inside a function which must reject the execution in some cases which aren't application errors. For example:

Services.data.isNotForbiddenFieldToUpdate(bodyKeys,forbidden)
.then(() => console.log('Finish'))

Where

isNotForbiddenFieldToUpdate: (fieldsToUpdate,forbiddenFields) => {
    var deferred = Q.defer();

    //DO A QUERY AND STORE IN result PARAM

    if(err)           deferred.reject(err)
    else if(! result) deferred.reject(new Error('Query is empty.'));
    else              deferred,resolve();
    return deferred.promise;
}

In this case, is not possible to return something different from deferred.promise. If I remove this and return true, the error is that then is unknown.

How could I manage this kind of code without using deferred if is possible? Thanks.

Joss
  • 535
  • 1
  • 8
  • 28
  • 1
    Is the query an asynchronous operation? If so, you're doing the right thing by returning a promise. Otherwise, don't return a promise. – Mike Cluck Jun 27 '16 at 15:42
  • Could you explicitly state the deferred antipattern that you are referencing? I'm really curious what you are trying to avoid. Promises are a tool to avoid callback hell. – zero298 Jun 27 '16 at 16:00

2 Answers2

0
isNotForbiddenFieldToUpdate: (fieldsToUpdate,forbiddenFields) => {
    var deferred = Q.defer();

    //DO A QUERY AND STORE IN result PARAM

At this point, assuming that the "QUERY" is an asynchronous operation, you will get back a promise. So you likely don't need to create another promise, just reuse the one coming from your "QUERY".

    return yourAsyncQuery();

Or, if you need to add things to the result of your "QUERY", then you have to give it a callback to execute when it completes. Inside that callback, you resolve or reject the Promise (Q).

    yourAsyncQuery().then(
        function(result) {
            if (! result)
                deferred.reject(new Error('Query is empty.'));
            // do more stuff with 'result'.
            deferred.resolve(result);
        }, 
        function(error) {
            deferred.reject(error);
        }
    );
    return deferred.promise;
}
C14L
  • 12,153
  • 4
  • 39
  • 52
0

I don't know how in Q is, but with native promises you can do as follows:

isNotForbiddenFieldToUpdate: (fieldsToUpdate,forbiddenFields) => 
    new Promise((resolve, reject) => {
        //DO A QUERY AND STORE IN result PARAM
        if(err){           
          reject(err);
        } else if(! result){
          reject(new Error('Query is empty.'));
        } else {
          resolve();
        }
    }

I guess with Q should be similar. Anyway, unless you need a very specific Q functionality, I would rather use native Promises.

jgldev
  • 191
  • 11
  • If your `//DO A QUERY AND STORE IN result PARAM` is asynchronous, it would net an `await` and the Promise constructor parameter needs to be an async function as well. But this would be an indicator of an antipattern.[1] How would you circumvent this? [1] https://stackoverflow.com/questions/43036229/is-it-an-anti-pattern-to-use-async-await-inside-of-a-new-promise-constructor – David Schumann May 29 '19 at 09:16