Node.js "on" function - What does it do? - node.js

var rd = readline.createInterface({
input: fs.createReadStream(file),
output: process.stdout,
terminal: false
});
rd.on('line', function(line) {
And is any way how to make "on" working synchronous. Code inside "on" loop need to be done before executing loop again. Is any way how to do that?

Generally, the on function registers an event handler for a specific event.
The readline::line event serves for this purpose:
Emitted whenever the input stream receives a \n, usually received when
the user hits enter, or return. This is a good hook to listen for user
input.
— NodeJS documentation
By the way, which keywords did you use for your search? I used nodejs readline.createInterface and the first result was this NodeJS documentation page!

Related

How to add continuous running code into nodejs postgresql client?

I'm stuck on a problem of wiring some logic into a nodejs pg client, the main logic has two part, the first one is connect to postgres server and getting some notification, it is as the following:
var rules = {} // a rules object we are monitoring...
const pg_cli = new Client({
....
})
pg_cli.connect()
pg_cli.query('LISTEN zone_rules') // listen to the zone_rules channel
pg_cli.on('notification', msg => {
rules = msg.payload
})
This part is easy and run without any issue, now what I'm trying to implement is to have another function keeps monitoring the rules, and when an object is received and put into the rules, the function start accumulating the time the object stays in the rules (which may be deleted with another notification from pg server), and the monitoring function would send alert to another server if the duration of the object passed a certain time. I tried to wrote the code in the following style:
function check() {
// watch and time accumulating code...
process.nextTick(check)
}
check()
But I found the onevent code of getting notification then didn't have a chance to run! Does anybody have any idea about my problem. Or should I doing it in another way?
Thanks!!!
Well, I found change the nextTick to setImmediate solve the problem.

Process Object Stdout and StdIn do not work as expected

I am using vsCode for NodeJS.
My code was simple. So I was expecting stdout should wait for input from console. Once input is given, then it should go to exit.
But once i do > node process
the program goes to exit directly.
file - process.js ->
process.stdout.write('Ask me something : ');
process.stdin.on('data', function(answer){
console.log(answer.toString());
});
console.log('exit')
process.exit();
Output:
c:\node-projects\demo-nodejs>node process
Ask me something : exit
c:\node-projects\demo-nodejs>
How can I use process object to get standard input/output/print/exit the code instead of using other readline object?
There are a few question/answers such as this one already on this site that probably answer what you are asking. Your code is not working because the line with process.stdin.on is not a synchronous callback method call, it is an event handler that waits for the 'data' event.
If I understand what you are trying to do, I think it is easiest to import the 'readline' module. It is built-in to the nodejs executable, but not loaded to your code execution environment unless you require it.
That would make your code look like this:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Ask me something : ', function(answer){
console.log(answer.toString());
console.log('exit')
process.exit();
});
Note that the rl.question method call executes right away and calls the function(answer) function when the user is done with text input. It can take some understanding and getting used to the asynchronous program control flow in NodeJS, you might have to rethink some of the rest of your program structure.
The offical documentation for the readline NodeJS module and function is here.

readable.on('end',...) is never fired

I am trying to stream some audio to my server and then stream it to a service specified by the user, the user will be providing me with someHostName, which can sometimes not support that type of request.
My problem is that when it happens the clientRequest.on('end',..) is never fired, I think it's because it's being piped to someHostReq which gets messed up when someHostName is "wrong".
My question is:
Is there anyway that I can still have clientRequest.on('end',..) fired even when the stream clientRequest pipes to has something wrong with it?
If not: how do I detect that something wrong happened with someHostReq "immediately"? someHostReq.on('error') doesn't fire up except after some time.
code:
someHostName = 'somexample.com'
function checkIfPaused(request){//every 1 second check .isPaused
console.log(request.isPaused()+'>>>>');
setTimeout(function(){checkIfPaused(request)},1000);
}
router.post('/', function (clientRequest, clientResponse) {
clientRequest.on('data', function (chunk) {
console.log('pushing data');
});
clientRequest.on('end', function () {//when done streaming audio
console.log('im at the end');
}); //end clientRequest.on('end',)
options = {
hostname: someHostName, method: 'POST', headers: {'Transfer-Encoding': 'chunked'}
};
var someHostReq = http.request(options, function(res){
var data = ''
someHostReq.on('data',function(chunk){data+=chunk;});
someHostReq.on('end',function(){
console.log('someHostReq.end is called');
});
});
clientRequest.pipe(someHostReq);
checkIfPaused(clientRequest);
});
output:
in the case of a correct hostname:
pushing data
.
.
pushing data
false>>>
pushing data
.
.
pushing data
pushing data
false>>>
pushing data
.
.
pushing data
console.log('im at the end');
true>>>
//continues to be true, that's fine
in the case of a wrong host name:
pushing data
.
.
pushing data
false>>>>
pushing data
.
.
pushing data
pushing data
false>>>>
pushing data
.
.
pushing data
true>>>>
true>>>>
true>>>>
//it stays true and clientRequest.on('end') is never called
//even tho the client is still streaming data, no more "pushing data" appears
if you think my question is a duplicate:
it's not the same as this: node.js http.request event flow - where did my END event go? , the OP was just making a GET instead of a POST
it's not the same as this: My http.createserver in node.js doesn't work? , the stream was in paused mode because the none of the following happened:
You can switch to flowing mode by doing any of the following:
Adding a 'data' event handler to listen for data.
Calling the resume() method to explicitly open the flow.
Calling the pipe() method to send the data to a Writable.
source: https://nodejs.org/api/stream.html#stream_class_stream_readable
it's not the same as this: Node.js response from http request not calling 'end' event without including 'data' event , he just forgot to add the .on('data',..)
The behaviour in case of a wrong host name seems some problem with buffers, if the destination stream buffer is full (because someHost is not getting the sended chunks of data) the pipe will not continue to read the origin stream because pipe automatically manage the flow. As pipe is not reading the origin stream you never reach 'end' event.
Is there anyway that I can still have clientRequest.on('end',..) fired
even when the stream clientRequest pipes to has something wrong with
it?
The 'end' event will not fire unless the data is completely consumed. To get 'end' fired with a paused stream you need to call resume() (unpiping first from wrong hostname or you will fall in buffer stuck again) to set the steam into flowMode again or read() to the end.
But how to detect when I should do any of the above?
someHostReq.on('error') is the natural place but if it takes too long to fire up:
First try to set a low timeout request (less than someHostReq.on('error') takes to trigger, as seems too much time for you) request.setTimeout(timeout[, callback]) and check if it doesn't fail when correct hostname. If works, just use the callback or timeout event to detect when the server timeOut and use one of the techniques above to reach to the end.
If timeOut solution fails or doesn't fits your requirements you have to play with flags in clientRequest.on('data'), clientRequest.on('end') and/or clienteRequest.isPaused to guess when you are stuck by the buffer. When you think you are stuck just apply one of the techniques above to reach to the end of the stream. Luckily it takes less time to detect buffer stuck than wait for someHostReq.on('error') (maybe two request.isPaused() = true without reach 'data' event is enought to determine if you are stuck).
How do I detect that something wrong happened with someHostReq
"immediately"? someHostReq.on('error') doesn't fire up except after
some time.
Errors triggers when triggers. You can not "immediately" detect it. ¿Why not just send a prove beacon request to check support before piping streams? Some kind of:
"Cheking service specified by the user..." If OK -> Pipe user request stream to service OR FAIL -> Notify user about wrong service.

node.js STDIN works with process.stdin, not when piped

I'm using require("child_process").spawn and calling an executable, which at the beginning is pausing for a password to be input; if I use it like below:
var spawn = require("child_process").spawn;
var exe = spawn("NameOfExe.exe", [/*arguments*/], {stdio: [process.stdin, process.stdout, process.stderr]});
It works perfectly (Yes, I know I can do inherit, shush :p ). I can type inside my console and it'll accept it with no issues.
However, if I do it like this:
var spawn = require("child_process").spawn;
var exe = spawn("NameOfExe.exe", [/*arguments*/], {stdio: ["pipe", process.stdout, process.stderr]});
exe.stdin.write("Password\n");
then the executable doesn't even receive the stdin; it immediately goes to Execution Failed.
I'm completely at a loss for this. Any suggestions?
EDIT:
I think I may be onto something!
So I'm 99.99% certain that the executable is using C# and Console.ReadKey to get the password. However, according to Microsoft, an exception gets thrown whenever the In property is redirected somewhere else.
So this explains it, but is there a way around this using Node, or am I at the mercy of the people who made this executable?
The ReadKey method reads from the keyboard even if the standard input is redirected to a file with the SetIn method.
You figured it out. It uses native bindings to the hardware controller/HAL, and not the shell, to handle stdio.

node REPL "on exit" event

Is there any way to trigger a function that's called when the user types .exit or [Ctrl][D]s the script?
Something like:
repl.start().on('exit', function() {
console.log("Thanks for using customized Node REPL!");
});
(Except, of course, I'd actually put useful code instead of the console.log.)
repl.start().rli.on('close', function() {
console.log("Thanks for using customized Node REPL!");
});
REPL uses the Readline module, which emits a Close event. From the docs:
Event: 'close'
function () {}
Emitted whenever the in stream receives a ^C or ^D, respectively known
as SIGINT and EOT. This is a good way to know the user is finished
using your program.

Resources