0

This will probably seem like a beginner's question but I've taught myself all I know about JS (thanks Stack Overflow!).

It's a problem of passing scope in a complicated way. I have a feeling that it has to be solved using apply or bind, which I have a hard time wrapping my mind around.

I have a Parser class to deal with many large CSV-like files I have. The files all contain different info and need to be handled differently. For the sake of demo, lets call them foo.csv and bar.csv. The example is oversimplified but it demonstrates the problem I have.

Constructor function :

function Parser() {
    this.csvFoo = './foo.csv';
    this.csvBar = './bar.csv';
    this.parsedInfo = {
        foos: [],
        bars: []
    };
}

Then I have 2 functions to handle the 2 types of files :

Parser.prototype._parseFoo = function(line, cb) {
    var fields = this._parseLine(line,',');
    this.parsedInfo.foos.push({
        foo1: fields[1],
        foo2: fields[2]
    });
    cb();
};

Parser.prototype._parseBar = function(line, cb) {
    var fields = this._parseLine(line,',');
    this.parsedInfo.bars.push({
        bar1: fields[1],
        bar2: fields[2]
    });
    cb();
};

And a function to split a line according to a delimiter :

Parser.prototype._parseLine = function(line, delim) {
    return (line.split(delim));
};

The function that streams the file and does the parsing is the following :

Parser.prototype._streamParseFile = function(file, makeObj, cb) {
    var self = this;
    var lineNum = 0;
    var s = fs.createReadStream(file).pipe(es.split()).pipe(es.mapSync(function(line) {
        s.pause();
        (function() {
            makeObj(line, function(sale) {
                s.resume();
            });
        })();
    }).on('error', function(err) {
        console.log('Error');
        console.log(err);
    }).on('end', function() {
        console.log('done');
        cb();
    }));
};

And I call it like this :

Parser.prototype.insertFoos = function() {
    var self = this;
    self._streamParseFile(self.csvFoo,self._parseFoo,function() {
        console.log('Done Foo');
    });
};

The problem I have is that when it arrives to _parseFoo, the "this" object isn't set properly, so in that case I cant use the this._parseLine().

I thought I could get away with using :

makeObj(line, function(sale) {
    s.resume();
}).bind(self);

but it doesn't work. I am reading docs and articles at the moment, but I know for a fact that it's an area I don't master, so a piece of explanation would help a lot.

xShirase
  • 10,351
  • 2
  • 43
  • 80
  • Another of these? Try `, self._parseFoo.bind(self), `. Also in `makeObj` you are not binding to the callback function, but to whatever `makeObj` returns. – elclanrs Jan 22 '15 at 00:14
  • Sorry if it's a boring one, the main problem when looking for this type of answer is how difficult it is to search for the right terms when you don't know exactly what to look for. You taught me something, thank you! – xShirase Jan 22 '15 at 00:19
  • 2
    Not boring, just common. If you want to look for more info check http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work and look for tutorials on how the `this` keyword works; I think it is often misunderstood. – elclanrs Jan 22 '15 at 00:29
  • Nice! Do you want to post an answer and get the points, or should I remove the question altogether to not clog the site with common questions? – xShirase Jan 22 '15 at 00:34
  • Too late, I'd just accept the answer below, removing `self` is a good point, because you don't need it there. – elclanrs Jan 22 '15 at 00:53

1 Answers1

2

You'll want to do

Parser.prototype.insertFoos = function() {
    this._streamParseFile(this.csvFoo, this._parseFoo.bind(this), function() {
//                                                   ^^^^^^^^^^^
        console.log('Done Foo');
    });
};

Notice that your es.mapSync callback is overly complicated (no reason for that IEFE!) and you (yet?) don't actually need a callback for makeObj - parseFoo is synchronous.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • yeah, like I said, the example is oversimplified, I actually have some async stuff going on in the real function ;) – xShirase Jan 22 '15 at 02:32