1

I'm making a post request and it requires several things to happen. It's native JavaScript promise not any library. Initially used nested promise and it was working but code was not that good. So, I decided to go with Promise chain and I'm stuck. The post route always returns {success:false, err:{}}, which it should when something goes wrong. But the err object is empty object. Why is that? After some tests I found the problem is in the second then where I'm returning AvaiablexForX.findOne({isX:false});. Don't worry about variables names, for the sake idea I have changed the actual names.

router.post("/delevery_request",
            passport.authenticate("jwt", {session:false}),
            (req, res) => {
            const requestInputFields = {};
            const foundxProfile = {};
            const xProfileId = "";
            const newxRequestId = "";
            requestInputFields.isAccepted = false;



            XProfile.findOne({user:req.user.id})
            .then(xProfile => {

                foundxProfile= xProfile;
                requestInputFields.xId = xProfile._id;
                return  AvaiablexForX.findOne({isX:false});
            })

            .then( avaiablexForX => 
                {
                    // this does not reach here
                  console.log("available x for X", avaiablexForX);
                  requestInputFields.xToBeDonateId =  avaiablexForX._id; 
                  xProfileId = avaiablexForX.xProfileId;

                  return requestInputFields;
             })
            .then( result => new RequestxY(result).save()).
            then( requestForxY => {

                foundxProfile.requestedxDeleivery.unshift(requestForxY._id);              
                return foundxProfile.save();

            }).
            then( xProfile => res.json({success:true}))
            .catch(err => {
                        //  output in body of request: {success:false, err:{}}
                        res.status(404).json({success:false, err:err})

            }
            );
          });
  • Are you sure about err being empty? It should carry stack info and some message. – dasfdsa Jun 26 '18 at 10:15
  • 1
    `JSON.stringify()` on `Error` instances often yields an empty object. Log it to a file instead of putting it in the response – Bergi Jun 26 '18 at 10:28

2 Answers2

0

Probably the problem is you trying to set a new value for const:

foundxProfile= xProfile;

This cause error and broke the chain. Try to replace all const by let.

0

Short answer: as already pointed out members declared with const can't be reassigned.

Long answer: you would benefit from a better strategy for accessing previous promise results in a .then() chain

With ref to the linked topic, you are using the "inelegant and rather errorprone" mutable contextual state.

You might consider one of the other approaches :

  • Nesting (and) closures
  • Break the chain
  • Explicit pass-through

For example, Nesting (and) closures would give you something like this :

router.post('/delevery_request', passport.authenticate('jwt', { 'session': false }), (req, res) => {
    XProfile.findOne({ 'user': req.user.id })
    .then(xProfile => {
        return AvaiablexForX.findOne({ 'isX': false })
        .then(avaiablexForX => {
            return new RequestxY({
                'isAccepted': false,
                'xId': xProfile._id,
                'xToBeDonateId': avaiablexForX._id
            }).save();
        })
        .then(requestForxY => {
            xProfile.requestedxDeleivery.unshift(requestForxY._id);
            return xProfile.save();
        });
    })
    .then(() => res.json({ 'success': true }))
    .catch(err => {
        res.status(404).json({
            'success': false,
            'err': err
        });
    });
});

Due to closure, xProfile is available to the first and second nested .then().

What was requestInputFields is composed on the fly where it is used.

You lose the nice flat line up of then()s but gain by not needing a bunch of messy outer members.

Roamer-1888
  • 19,138
  • 5
  • 33
  • 44