0

Currently I'm working with Node, Express and the Q library for promises. It works fine but I'm inserting each promise inside the following getting a horrible pyramid of doom.

I've checked I can avoid this with the following structure:

function validateInputFields(formName,req){
    var deferred = Q.defer()
      , connection  = req.conn || deferred.resolve(new Error('Internal error with connection.'));

    Services.data.splitBody(req.body)
    .then((arr) => {
        var inputFields = arr[0]
          , inputValues = arr[1];

        return Services.form.getFields(connection,formName)
    })
    .then((formKeys)            => { return Services.form.getMandatories(formKeys) })
    .then((dbMandatories)       => { return Services.form.allMandatoriesAreProvided(dbMandatories,inputFields) })
    .then((mandatoriesProvided) => { return Services.form.allFieldsBelongToform(formKeys,inputFields) })
    .then(()                    => {
        Services.form.correctFieldsType(inputFields,inputValues,formKeys)
        deferred.resolve();          
    })
    .catch((err) => next(err));

    return deferred.promise;
}

The problem here is that I can't access to some vars such as inputFields in the following promises and I was able to do when they where nested.

Other post suggest to use .spread in spite of .then but it doesn't work (even promises stop working).

Is there a smart way to solve this?

Thanks!

Community
  • 1
  • 1
Joss
  • 535
  • 1
  • 8
  • 28
  • if you declare the inputFields,inputValues variables at the start of your function you could use them where you need. But I am not sure if this is the real solution in the problem you face. – Alex Michailidis Jun 10 '16 at 13:17
  • @alex-rokabilis: It's a solution, yes, albeit a horrible one. – Bergi Jun 10 '16 at 13:31
  • Avoid the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Jun 10 '16 at 13:31
  • @bergi I disagree completely. @alex-rokabilis has the right idea, and it's the simplest solution. Since `inputFields` and `inputValues` will be declared within the closure of `validateInputFields()`, you don't need to worry about them being overwritten in subsequent calls. Also since it may not be clear, using closure scoped variables is not the deferred antipattern, that's a different issue in the code provided. – hotforfeature Jun 10 '16 at 13:34
  • Also note that `arr` is `req.body`, which is already declared in the closure outside of the promises. There's nothing wrong with aliasing `req.body[0]` to `inputFields` before the promise calls – hotforfeature Jun 10 '16 at 13:36
  • @hotforfeature: No, it's not the simplest and not the best solution, see the duplicate for alternatives. Yes, the deferred antipattern is an unrelated issue. – Bergi Jun 10 '16 at 13:49
  • @hotforfeature: Uh, what does `Services.data.splitBody(req.body)` do if its input and output are the same? Why not completely omit it (I don't know that library)? If you think that would be a better answer, feel free to cast a reopen vote. Still, accessing `formKeys` is a promise result and I don't think you can simplify that. – Bergi Jun 10 '16 at 14:02

0 Answers0