0

I'm making a temporary fake API and am trying to set up a simple request response script in node using express.js to achieve this. It's very strraightforward, A request comes in, is validated and, if valid, is merged with a .json template file and the result returned, thus giving the impression the user was successfully created.

  app.post('/agent/user', function(req, res){
    var responseTemplate = new jsonRequired('post_user');
    var errorTemplate = new jsonRequired('post_user_error');
    var payload = req.body;
    var responseData;
    var hasErrors = false;

    console.log('Creating new user');
    //Recursive Merge from http://stackoverflow.com/a/383245/284695

    responseData = new mergeRecursive(responseTemplate,payload);

    if(!payload.username){
      hasErrors = true;
      errorTemplate.errors.username.push('A username is required.');
    }

    if (hasErrors){
      res.send(errorTemplate,422);
    }else{
      res.send(responseData,200);
    }

  });

The problem I'm having is that data is persisting between calls. So if I define a username and name[first] in 1 request and just a username in the 2nd one, both requests come back with the name[first] property.

I have a feeling it's something to do with js closures. Unfortunately, every tutorial I find seems to be about making closures, not avoiding them.

It should work like this:

  1. The client POST's username=user1&name[first]=joe&name[last]=bloggs
  2. The Server loads a json file containing a prepopulated user object: e.g.

    {"username":"demo","name":{"first":"John","last":"Doe"}...}

  3. mergeRecursive() merges the payload from the POST request over the template object and returns the new object as the POST response text.

The problem is that with every new request, the server is using the result of step 3 in step 2 instead of reloading the .json file.

5
  • Could you possible give more explanation on what you are trying to do? Frankly i did not quite get your problem. Commented Nov 23, 2012 at 12:14
  • I've added an explanation for you. Hope it clears it up Commented Nov 23, 2012 at 12:23
  • This should happen since youre merging with your json template and your json template by default contains a "name[first]" property. Commented Nov 23, 2012 at 12:27
  • Yes but if a 2nd POST request has, for example, no last name I would expect it to use the default Doe rather than bloggs Commented Nov 23, 2012 at 12:33
  • Thats bcz of merging. You simply merge things. so if one does not have it, then result will still have it. Commented Nov 23, 2012 at 12:41

3 Answers 3

1

That mergeRecursive function has the same caveat as jQuery.extend: it modifies the first object sent into it. In fact, you don't even need to use its return value.

You didn't show the code of jsonRequired function (it's not even clear why you've used new when invoking it), but it looks like this function doesn't create a new object each time it's called, instead fetching this object from some outer repository. Obviously, mergeRecursive modifications for it won't be lost after that function ends.

The solution is using your data object for merging. Like this:

var responseData = {};
...
mergeRecursive(responseData, responseTemplate);
mergeRecursive(responseData, payload);
Sign up to request clarification or add additional context in comments.

2 Comments

jsonRequired(file) just a small helper that returns a json file with return require(dir+file+extension);
And require caches the loaded objects in require.cache global object (doc), so all subsequent calls will return these instead.
0

Merging two objects will make this for you.

If your responseTemplate has parameter, which actual request did not have, then you will end up having it there. Check definition of word merge ;)

Comments

0

While this doesn't resolve the issue I had, I have found a workaround using the cloneextend package available via npm:

$ npm install cloneextend

This allows me to use the following js:

var ce = require('cloneextend');

...

ce.extend(responseData, responseTemplate);
ce.extend(responseData, payload);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.