0

How to fix this code in TypeScript (ES5+) such that the callback function of readInterface.on() can access the lines array declared outside the function?

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

const readInterface = readline.createInterface({
  input: fs.createReadStream("data.list"),
  output: false,
  silent: true,
  console: false
});

var lines: string[] = [];

readInterface.on('line', function(line) {
  if (line && line.indexOf("#") !== 0) {
    this.lines.push(line);
  }
});

lines.forEach(line => {
  console.log(line);
});

Edit:

The solution

In fact this question posed to problems to tackle. The first error was resolved by @Andreas by outlining that the this keyword should be removed from the line this.lines.push(line);

The desired outcome of the question, however, was to synchronously return the lines read by the asynchronous function readInterface.on('line', function(line) { ... });, with the misunderstanding that the function was actually synchronous.

The solution was to use the synchronous alternative readlinesSync from a package available on npm as readlines.

const readlines = require('readlines');

var _lines: string[] = readlines.readlinesSync('dat/test.list');
var lines: string[] = [];

_lines.forEach(line => {
  if (line && line.indexOf("#") !== 0) {
    lines.push(line);
  }
});

lines.forEach(line => {
  console.log(line);
});
Waleed Qidan
  • 1,072
  • 10
  • 12
  • 1
    `line.indexOf("#") !== 0 && line` - The other way round would make more sense – Andreas Nov 16 '19 at 14:33
  • 1
    Why did you add `this`? – Andreas Nov 16 '19 at 14:33
  • console.log(lines[0]); still returns undefined without adding `this`. – Waleed Qidan Nov 16 '19 at 14:42
  • 1
    That's a different problem, hence a separate question -> [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Andreas Nov 16 '19 at 14:44
  • Constantly changing the question doesn't help - especially not when you remove the source of the problem/question – Andreas Nov 16 '19 at 14:46
  • None of the modifications reflect on the answer to the question anyway. How would you change the code above such that it compiles without an error? Please answer that if it's possible. – Waleed Qidan Nov 16 '19 at 14:52
  • See below. And as already said, the _"why is lines[0] still `undefined`?"_ -> That's a different problem, hence would require a different question which would then be closed as duplicate from the link I've mentioned in my third comment – Andreas Nov 16 '19 at 14:57
  • Thank you, though that question is about returning a response. This question is about mutating a globally declared property from within a callback function. – Waleed Qidan Nov 16 '19 at 15:05
  • No it is not: _"TypeError: Cannot read property 'push' of undefined"_ – Andreas Nov 16 '19 at 15:06

2 Answers2

2
readInterface.on('line', line=> {
  if (line.indexOf("#") !== 0 && line) {
    this.lines.push(line);
  }
});

Using arrow functions in typescript helps you to point the right this reference. Else you reference the closure you are currently in.

Eldar
  • 9,781
  • 2
  • 10
  • 35
  • _"Else you reference the function you are currently in"_ -> [How does the “this” keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Andreas Nov 16 '19 at 14:37
0

Remove this in this.lines.push()

readInterface.on('line', function(line) {
  if (line && line.indexOf("#") !== 0) {
    lines.push(line);
  }
});

-> How does the "this" keyword work?

Andreas
  • 21,535
  • 7
  • 47
  • 56
  • this only fixes the first half of the problem. running `console.log(lines[0]) after the call to corrected readInterface.on() still returns `undefined`. – Waleed Qidan Nov 16 '19 at 14:59
  • As already said _twice_. That's the answer to the problem in your title/question. The "second half" is a different problem (-> hence a different question) which I've also "answered" _twice_... – Andreas Nov 16 '19 at 15:01