Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused by Node.js readline on() method

I am confused by some simple behavior I see from readline on() method.

I have a file called small.csv which looks like this:

Date,Close
2015-11-12,2045.97
2015-11-11,2075.00
2015-11-10,2081.72
2015-11-09,2078.58

I wrote this script:

my.js

var rl = require('readline').createInterface({
  input: require('fs').createReadStream('small.csv')
});

global.myarray = [];
rl.on('line', function (line) {
  console.log('Line from file:', line);
  global.myarray.push(line);
});

console.log(global.myarray);
// done

Script Output:

dan@nia111:~/d1d2p $ 
dan@nia111:~/d1d2p $ node -v
v5.0.0
dan@nia111:~/d1d2p $ 
dan@nia111:~/d1d2p $ 
dan@nia111:~/d1d2p $ node my.js
[]
Line from file: Date,Close
Line from file: 2015-11-12,2045.97
Line from file: 2015-11-11,2075.00
Line from file: 2015-11-10,2081.72
Line from file: 2015-11-09,2078.58
dan@nia111:~/d1d2p $ 
dan@nia111:~/d1d2p $ 

I want to enhance the script so it fills global.myarray rather than leaving it empty.

When I step through the script with node-debug, it appears that global.myarray is filling but I think that it is an illusion.

Also when I run node my.js it appears that console.log(global.myarray);

runs before small.csv is read.

So I probably need to understand some asynchronous mechanism at work here.

The following question might be easy for those who understand readline well.

But, I'd be happy to get an answer to this question:

How to enhance my.js so it fills global.myarray rather than leaving it empty?

like image 669
user3676943 Avatar asked Nov 13 '15 09:11

user3676943


1 Answers

Because of it's asynchronous nature Node.js can be a bit tricky with this kind of things. It means that when your code is executing, it is firing the rl.on('line') handler and passing to the next call which in our case is the console.log. The problem in your actual code is not that the array is not filling up, it's that you are expecting it to be populated to early. Here is an example of how you could fix your problem:

var rl = require('readline').createInterface({
  input: require('fs').createReadStream('small.csv')
});

global.myarray = [];
rl.on('line', function (line) {
  console.log('Line from file:', line);
  global.myarray.push(line);
});

rl.on('close', function () {
    console.log(global.myarray);
});

In this piece of code, when there is no more line to read from, the console.log will be called and there will be some data displayed.

like image 160
prichrd Avatar answered Sep 30 '22 10:09

prichrd