Reputation: 526
When I have multiple readline objects, even when they are opened and closed within the same closure, I end up seeing strange behavior.
In the tick tac toe game I am practicing making, I run into the issue where readline.interface.question
terminates without receiving input, and without entering the callback.
In the case below, where I have tried to isolate the issue, prompts occasionally duplicate my inputs (ex. typing "1" results in "11")
How should readline.interface.question
be used synchronously?
const EventEmitter = require('events');
const readline = require('readline');
function Emitter() {
EventEmitter.call(this);
this.val = 1;
this.ping = () => {
console.log(this.val);
readAndPrint(() => {
this.emit('emit');
});
}
this.setEmitter = (emitter) => {
emitter.on('emit', this.ping);
}
const readAndPrint = (callback) => {
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
reader.question('Enter a string: ', (answer) => {
reader.close();
console.log(answer);
callback();
})
}
}
Emitter.prototype.__proto__ = EventEmitter.prototype;
let one = new Emitter();
let two = new Emitter();
let three = new Emitter();
one.setEmitter(three);
two.setEmitter(one);
three.setEmitter(one);
one.ping();
Upvotes: 2
Views: 240
Reputation: 43
My guess is that because all your this.pings are triggered by the same "emit" when you setEmitter. So after your one.ping() the callback trigger an "emit" and this.ping for two,three go off after one is closed.
You can try giving each emitter an id so they dont all trigger each emitter's this.ping
const EventEmitter = require("events");
const readline = require("readline");
function Emitter(id) {
EventEmitter.call(this);
this.val = 1;
this.id = id;
this.ping = () => {
console.log(this.val);
readAndPrint(() => {
this.emit("emit" + this.id);
});
};
this.setEmitter = emitter => {
emitter.on("emit" + this.id, this.ping);
};
const readAndPrint = function(callback) {
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout
});
reader.question("Enter a string: ", answer => {
reader.close();
console.log(answer);
callback();
});
};
}
Emitter.prototype.__proto__ = EventEmitter.prototype;
let one = new Emitter(1);
let two = new Emitter(2);
let three = new Emitter(3);
one.setEmitter(three);
two.setEmitter(one);
three.setEmitter(one);
one.ping();
Here is a snippet to give you a better understanding of what's happening. Basically your code calls one.ping(), it closes then two.ping and three.ping go off from your callback "emit"
const EventEmitter = require("events");
const readline = require("readline");
function Emitter(id) {
EventEmitter.call(this);
this.val = 1;
this.id = id;
this.ping = () => {
readAndPrint(() => {
this.emit("emit");
});
};
this.setEmitter = emitter => {
emitter.on("emit", this.ping);
};
const readAndPrint = callback => {
console.log("my id is:", this.id);
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout
});
reader.question("Enter a string: ", answer => {
reader.close();
console.log(answer);
callback();
});
};
}
Emitter.prototype.__proto__ = EventEmitter.prototype;
let one = new Emitter(1);
let two = new Emitter(2);
let three = new Emitter(3);
one.setEmitter(three);
two.setEmitter(one);
three.setEmitter(one);
one.ping();
To do it synchronously, you can use callbacks like so:
const EventEmitter = require("events");
const readline = require("readline");
function Emitter(id) {
EventEmitter.call(this);
this.val = 1;
this.id = id;
this.ping = cb => {
readAndPrint(() => {
this.emit("emit" + this.id);
if (cb) {
cb();
}
});
};
this.setEmitter = emitter => {
emitter.on("emit" + this.id, this.ping);
};
this.removeListener = emitter => {
emitter.removeListener();
};
const readAndPrint = callback => {
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout
});
reader.question("Enter a string: ", answer => {
console.log("my id is: ", this.id);
reader.close();
console.log(answer);
callback();
});
};
}
Emitter.prototype.__proto__ = EventEmitter.prototype;
let one = new Emitter(1);
let two = new Emitter(2);
let three = new Emitter(3);
one.setEmitter(three);
two.setEmitter(one);
three.setEmitter(one);
one.ping(() => two.ping());
Upvotes: 1