UG_ UG_ - 4 months ago 16
Node.js Question

Variable not updating inside requestJS's data event

I am trying to cache response from a url to a variable and send it on subsequent request. For this I am writing to variable on data event of request. The variable is updated but I am not able to access it out of the event's callback.

Below is the code and log I generated out of it.

I am not able to understand why despite getting updated in

data
event callback it's length is 0 in
end
event callback.

Note :
data
variable has url attribute,
req
and
res
request and response variables.

var cache = {} ; //global variable
function get_from_box_cached (data,req,res){
var options = _.extend({}, REQUEST_OPTIONS, {url : data.url, method: req.method}) ;

if (cache[data.url]){
console.log(data.url + "available in cache");
res.send(cache[data.url]);
}else{
cache[data.url] ="";
var request_to_server = request(options);
request_to_server.on('data', function(data){
cache[data.url] += data.toString('ascii');
console.log("data event : cached : " + cache[data.url].length);

});
request_to_server.on('end', function(){
console.log("end event : cached : " + cache[data.url].length);
});
}
}


Log :

data event : cached : 8201
data event : cached : 8556
data event : cached : 16393
data event : cached : 17548
data event : cached : 24585
data event : cached : 32777
data event : cached : 40969
data event : cached : 49161
data event : cached : 57353
data event : cached : 65545
data event : cached : 73737
data event : cached : 81929
data event : cached : 90121
data event : cached : 98313
data event : cached : 102941
end event : cached : 0


Calling code :

app = require('express)();
app.all('/abc/*',function (req, res) {
var data = {};
data.url = SERVER_URL + "/" + url.parse(req.url).path;
get_from_box(data,req,res);
});

Answer

You can create a simple cache object module, that way you don't pollute the global object and it may help for debugging purposes, i.e. you can print some info each time the data is changed (make sure to only change the data property using the append/clear methods, not directly).

e.g. cache.js:

module.exports = {
    data: [],
    append: function(url, data) {
        if (!this.data[url]) { this.data[url] = ''; } // initialize
        this.data[url] += data;
        console.log('cache[' + url + '] length:', this.data[url].length);
    },
    clear: function(url) {
        if (url) {
            delete this.data[url];
            console.log('removed', url, 'from cache');
        }
        else {
            this.data = [];
            console.log('cleared cache');
        }
    }
}

Then in your main script:

var cache = require('./cache');

request_to_server.on('data', function(data) {
    cache.append(data.url, data.toString('ascii'));
}

You can also require() the module in any other script and it will keep its data, because that is how modules work in Node.js.

Comments