Iolo
Iolo

Reputation: 2232

Why is node.js variable persisting

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.

Upvotes: 0

Views: 107

Answers (3)

Iolo
Iolo

Reputation: 2232

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);

Upvotes: 0

Alexey Kamenskiy
Alexey Kamenskiy

Reputation: 2948

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 ;)

Upvotes: 0

raina77ow
raina77ow

Reputation: 106385

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);

Upvotes: 1

Related Questions