Joe Ali
Joe Ali

Reputation: 33

How to force sequential statement execution in Node?

I am new to Node, so please forgive me if my question is too simple. I fully appreciate the Async paradigm and why it is useful in single threads. But some logical operations are synchronous by nature.

I have found many posts about the async/sync issue, and have been reading for whole two days about callbacks, promises, async/await etc...

But still I cannot figure what should be straight forward and simple thing to do. Am I missing something!

Basically for the code below:

const        fs = require('fs');
var   readline  = require('readline');


function getfile (aprodfile) {

   var prodlines = [];

   var  prodfile = readline.createInterface({input: fs.createReadStream(aprodfile)});

   prodfile.on('line', (line) => {prodlines.push(line)});
   prodfile.on('close', () => console.log('Loaded '+prodlines.length));

  // the above block is repeated several times to read several other
  // files, but are omitted here for simplicity

   console.log(prodlines.length);

   // then 200+ lines that assume prodlines already filled
};

the output I get is:

0
Loaded 11167

whereas the output I expect is:

Loaded 11167
11167

This is because the console.log statement executes before the prodfile.on events are completed.

Is there a nice clean way to tell Node to execute commands sequentially, even if blocking? or better still to tell console.log (and the 200+ lines of code following it) to wait until prodlines is fully populated?

Upvotes: 1

Views: 293

Answers (1)

Jeremy Thille
Jeremy Thille

Reputation: 26410

Here's the execution order of what you wrote :

prodfile.on('line', line => { // (1) subscribing to the 'line' event
    prodlines.push(line) // (4), whenever the 'line' event is triggered
});

prodfile.on('close', () => { // (2) subscribing to the 'close' event
    console.log('Loaded '+prodlines.length) // (5), whenever the 'close' event is triggered
});


console.log(prodlines.length); // (3) --> so it logs 0, nothing has happened yet

What you can do is this :

function getfile (aprodfile) {

   var prodlines = [];

   var  prodfile = readline.createInterface({input: fs.createReadStream(aprodfile)});

   prodfile.on('line', line => { prodlines.push(line) });
   prodfile.on('close', () => { 
        console.log('Loaded '+prodlines.length)
        finishedFetching( prodlines );
   });
};


function finishedFetching( prodlines ) {
     console.log(prodlines.length) // 200!
}

Upvotes: 2

Related Questions