-2

I have a rest api that receives a patch request with the following possible parameters:

  • firstname
  • lastname
  • image
  • birthday

If I receive the image parameter I will need to upload the image to a cdn and after that to update and save the user profile. If I don't receive the image parameter I will update and save the user profile.

What I had in mind was: if photo then upload -> promise -> update fields -> save else update fields -> save

My question: is there a best practice so I don't need to double a portion of code for each case?

app.patch('/users', authenticate, (req, res) => {
  let body = _.pick(req.body, ['birthday', 'country', 'city', 'gender', 'firstname', 'lastname', 'photo']);

  if ( body.photo ){
    cloudinary.uploader.upload(body.photo,function(error, result) {
      if( error ) {
        res.status(400).send(error);
      }
      body.photo = result.url;
      req.user = { ... req.user, ... body};
      console.log ('update profile');
      res.send(req.user);
    });
  }

  req.user = { ... req.user, ... body};
  console.log ('update profile');
  res.send(req.user);
});
neko
  • 23
  • 8
  • Couldn't you just move update fields to a method and re use that? Please post some code for your question to be interpreted in a better way – yaswanth Jul 18 '18 at 12:38
  • do you mean you'll have to write duplicate for saving? I think if your promise chain carries smartly set values you won't have any duplication for that flow –  Jul 18 '18 at 12:49
  • @aec I'm kinda new to async/callback programing and having a hard time thinking like this. Do you have some resources that I can read to help me with this problem ? – neko Jul 18 '18 at 13:09
  • I would advice you to try to write a promise-driven solution to your problem without my help. But if you need the help, my solution is in the answers. –  Jul 18 '18 at 13:30

1 Answers1

1

I have assumed that there is a createUser function that return a promise.

let userData = req.body;
userData.photo = undefined;

return Promise.resolve()
    .then(function() {
        if (req.body.photo) {
            return promisifiedUpload(body.photo);
        } else {
            return undefined;
        }
    })
    .then(function(result) {
        if (result && result.url) {
            userData.photo = result.url;
        }

        return createUser(userData);        
    })
    .then(function(it) {
        res.send(it);
    })
    .catch(function(err) {
        res.status(400).send(err);
    });

There are plenty of helper libraries that help you turn functions that work with node-style callbacks like function(err, resp){...} to promises, but for the sake of clarity this is how you could use one:

function promisifiedUpload(url) {
    return new Promise(function(resolve, reject) {
        cloudinary.uploader.uproad(url, function(err, resp) {
            if (err) {
                reject(err);
            } else {
                resolve(resp);
            }
        });
    });
}

Some material that might come in handy: