Weird node.js console.log() output behaviour when printing arrays - node.js

I have the following, somewhat simple code in VSCode(Mac OS) which I run in node.js v14.13.1 environment:
let fruits = ['Apple', 'Banana'];
let fruits1 = ['Apple1', 'Banana1'];
console.log(fruits);
console.log(fruits1);
The output behaviour seems very weird to me, it prints either:
(2) ['Apple', 'Banana']
or
(2) ['Apple', 'Banana']
(2) ['Apple1', 'Banana1']
or
(2) ['Apple', 'Banana']
Canceled
I couldn't find any particular pattern of printing (except for first two outputs are printed more often than the third one), so it seems as if it 'randomly decides' what to output.
This code, however, outputs always as expected when executed via Mac terminal(node my_file.js), i.e.:
[ 'Apple', 'Banana' ]
[ 'Apple1', 'Banana1' ]
Is that some kind of VSCode bug, or there is something about printing arrays with console.log() (with strings and integers it works just fine) what I don't take into account?

One solution you could try is to convert the array to a string when doing the console.log command:
let fruits = [['Apple', 'Banana'],['Apple', 'Banana']];
console.log(fruits.toString()); // Apple,Banana,Apple,Banana
console.log('' + fruits); // Apple,Banana,Apple,Banana
console.log(JSON.stringify(fruits)); // [["Apple","Banana"],["Apple","Banana"]]
I like the last one because it keeps this array displayed within brackets, even with multidimensional arrays.
However, one problem I found with this is when working with regular expression, there is addition output lost when converting to a string:
let str = 'xyz';
let pat = /y/;
let res = str.match(pat);
console.log(res); // ['y', index: 1, input: 'xyz', groups: undefined]
console.log(res.toString()); // y
console.log('' + res); // y
console.log(JSON.stringify(res)); // ["y"]
I believe this error may be occurring because the debugger is stopping before the output is sent to the debug console? Therefore For another solution, either add an empty line at the end of your code and add a breakpoint there; this seems to allow all the output to be generated when doing a multiple console.logs on arrays. Or, at the end of the code, add:
setTimeout(() => { }, 1000)
Which also seems to be adding enough time to properly output all the console.log of arrays. The advantage to the former is, you can expand the array details in the debug console, until you continue to the end of the code, but the con is you still have to chose to continue the code for it to end. The latter also allows you to expand the details of the object in the output, but only for the duration of the timer.
I also found, you can add either of these to your launch.json file (within the appropriate node configuration object, and don't forget to add a common to either the end the line before and/or the the end of either of these lines depending on where you are inserting):
"console": "integratedTerminal"
Or:
"console": "externalTerminal"
These send the output to either the VS Code terminal pane or an external cmd window.
And finally I also found instead of either of these console command, you can add this to the launch.json:
"outputCapture": "std"
This will keep the output in the debug console. It looks a bit different with color & some other messages, but seems to successfully output arrays.

I have the same problem. I think it is some kind of VSCode bug.
When I print the data in a event callback, console.log behave as expected. But after a while, the main thread exists and console.log output Canceled.
import some modules...
vtgeojson(tiles, { tilesOnly: true })
.on('data', function (data) {
featurecollection.features.push(data);
console.log(data)
})
.on('end', function () {
console.log(featurecollection);
console.log(featurecollection.features.length);
})
The problem disappears when I set the breakpoint and print the data line by line.
The problem also disappears when I run the script in the powershell.
Although the console.log is canceled, the data has been successfully pushed into the feature list. The behavior is most likely caused by the vscode terminal or the way that vscode handle the console.log command.
My node version is v12.20.0 and VSCode version is:
Version: 1.51.1 (system setup)
Commit: e5a624b788d92b8d34d1392e4c4d9789406efe8f
Date: 2020-11-10T23:34:32.027Z
Electron: 9.3.3
Chrome: 83.0.4103.122
Node.js: 12.14.1
V8: 8.3.110.13-electron.0
OS: Windows_NT x64 10.0.17763
I find someone else has a similar problem.
console.log() is “Canceled” when looping unattended

This seems quite interesting. I have tried running it multiple times and got the same result as output from Chrome's console:
["Apple", "Banana"]
["Apple1", "Banana1"]
The issue could be related either to the version of Node.js you are running on your computer or the terminal on the version of VSCode you have.
Because I tried running it from the VSCode terminal and got the same result:

Related

How to get expandable objects view as output in VS Code node terminal?

I would like to have collapsible/ expandable objects in the terminal output in VS Code like on the browser console.
Here is an example:
In the debug terminal it works only if I toggle a breakpoint before the end of the program, but otherwise I get the error "No debugger available, can not send 'variables'".
So I'm thinking if the functionality is there, there must be a way to get it even without setting breakpoints every time. Right?
Use console.dir() instead of console.log().
Use this following example, to display all nested objects:
console.dir(yourStuff, { depth: null })
use
"outputCapture": "std"
in launch.json

Text in Bash terminal getting overwritten! Using JS, Node.js (npms are: inquirer, console.table, and mysql)

Short 10sec video of what is happening: https://drive.google.com/file/d/1YZccegry36sZIPxTawGjaQ4Sexw5zGpZ/view
I have a CLI app that asks a user for a selection, then returns a response from a mysql database. The CLI app is run in node.js and prompts questions with Inquirer.
However, after returning the table of information, the next prompt overwrites the table data, making it mostly unreadable. It should appear on its own lines beneath the rest of the data, not overlap. The functions that gather and return the data are asynchronous (they must be in order to loop), but I have tried it with just a short list of standard synchronous functions for testing purposes, and the same problem exists. I have tried it with and without console.table, and the prompt still overwrites the response, as a console table or object list.
I have enabled checkwinsize in Bash with
shopt -s checkwinsize
And it still persists.
Is it Bash? Is it a problem with Inquirer?
I was having this issue as well. In my .then method of my prompt I was using switch and case to determine what to console log depending on the users selection. Then at the bottom I had an if statement checking to if they selected 'Finish' if they didn't I called the prompt function again, which I named 'questionUser'.
That's where I was having the issue, calling questionUser again was overriding my console logs.
What I did was I wrapped the questionUser call in a setTimeout like this:
if(data.option !== 'Finish'){
setTimeout(() => {
questionUser();
}, 1000);
}
This worked for me and allowed my console log data to not get deleted.
Hopefully if anyone else is having this issue this helps, I couldn't find an answer to this specific question anywhere.

Find out what file is requiring another file in Node

The title says pretty much what I need to do.
I have a module in node_modules which prints something to the standard output (and I don't want this to happen) but I don't find where I'm requiring this file.
I may be misunderstanding how modules are included, as I though that they must be required in order to be executed.
There are multiple ways for stuff to write to output. If it's just using console.log(), just swap in trace. Before your require() statements:
console.log = console.trace;
Then, you'll have the full trace output every time there's a log.
Using this console.log mod :
let old = console.log;
console.log = function(){
return old.apply(this,[].slice.apply(arguments).concat([(new Error()).stack.split(/\n/)[2].trim()]));
}
If you try :
console.log('I am trackable!')
You will get as output :
I am trackable! at test (/path/solution.js:5:9)
Happy hunting!

node tty ReadStream _handle is null

I am trying to write an Electron launcher for the test runner testem. Testem prints to the terminal the test results from each of it's launchers (forked processes where tests get executed, traditionally browsers but in this case Electron). Testem wants to set the tty to 'Raw Mode' so it can make a faux-tabbed view that appears to update live, and lets the user navigate between tabs to see results from different launchers.
I'm seeing this error in my terminal after testem tries to call process.stdin.setRawMode (on node v4.0.0 on OS X Yosimite):
TypeError: Cannot read property 'setRawMode' of null
at ReadStream.setRawMode (tty.js:49:15)
at module.exports.View.extend.setRawMode (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/ui/appview.js:255:21)
at module.exports.View.extend.cleanup (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/ui/appview.js:265:10)
at EventEmitter.App.cleanupView (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:254:15)
at /Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:230:14
at /Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:325:23
at Object.HookRunner.run (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/hook_runner.js:13:14)
at EventEmitter.App.runHook (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:322:12)
at EventEmitter.App.runExitHook (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:312:10)
at /Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:229:12
at /Users/beane/Code/yeti-desktop/node_modules/testem/node_modules/async/lib/async.js:52:16
at Object.async.forEachOf.async.eachOf (/Users/beane/Code/yeti-desktop/node_modules/testem/node_modules/async/lib/async.js:236:30)
at Object.async.forEach.async.each (/Users/beane/Code/yeti-desktop/node_modules/testem/node_modules/async/lib/async.js:209:22)
at EventEmitter.App.cleanUpLaunchers (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:365:11)
at EventEmitter.App.quit (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:228:10)
at process.App.quiteGracefully (/Users/beane/Code/yeti-desktop/node_modules/testem/lib/dev/index.js:43:10)
The stacktrace begins at tty.js:49 from node core. Here's the function where the error is thrown from:
ReadStream.prototype.setRawMode = function(flag) {
flag = !!flag;
this._handle.setRawMode(flag);
this.isRaw = flag;
};
What I can't seem to figure out is what the heck this._handle is. Testem is not expecting it to be null, but for some reason it is. Can anyone help me out with this?

Muting stdout and stderr during Mocha tests

I'll preface this by admitting that I'm probably doing something I shouldn't be doing. But since I'm already this deep, I might as well understand why things are happening this way.
I am using Mocha to test some Node.js code. This code uses the Winston logging library, which directly calls process.stdout.write() and process.stderr.write() (source). It works well; I have no complaints about that behavior.
However, when I unit-test this code, the output of the Mocha test runner is occasionally interspersed with lines of log output, which is ugly in some reporters (dot, bdd) and downright invalid in others (xunit). I wanted to block this output without modifying or subclassing Winston, and I wanted to avoid modifying the application itself if I could avoid it.
What I arrived at was a set of utility functions that can temporarily replace the Node builtins with a no-op function, and vice versa:
var stdout_write = process.stdout._write,
stderr_write = process.stderr._write;
function mute() {
process.stderr._write = process.stdout._write = function(chunk, encoding, callback) {
callback();
};
}
function unmute() {
process.stdout._write = stdout_write;
process.stderr._write = stderr_write;
}
Inside the various test specs, I called mute() directly before any call or assertion that produced unwanted output, and unmute() directly after. It felt a little hacky, but it worked -- not a single byte of unwanted output appeared on the console when running the tests.
Now it gets weird!
For the first time, I tried redirecting the output to a file:
mocha spec_file.js > output.txt
The unwanted output came back! Every piece of output that was sent to stdout appears in the file. Adding 2>&1, I get stderr in the file too. Nothing appears on the console in either case, though.
Why would the test code behave so differently between the two invocations? My gut guess is that Mocha is doing some sort of test to determine whether or not it's writing to a TTY, but I couldn't spot an obvious place where it changes the behavior of its writes.
Also the broader question, is there any correct way to mute stdout/stderr during tests, without wrapping all potentially-logging app code in a conditional that checks for the test environment?
See https://www.npmjs.org/package/mute
it('should shut the heck up', function (done) {
var unmute = mute()
app.options.defaults = true;
app.run(function() {
unmute();
helpers.assertFiles([
['package.json', /"name": "temp-directory"/],
['README.md', /# TEMP.Directory/]
]);
done();
});
});
I discovered a likely cause for this behavior. It does indeed have to do with whether or not stdout/stderr is a TTY.
When the script runs in a console, these are both TTYs, and process.stdout and process.stderr appear to be instances of tty.WriteStream and not, as I originally assumed, a stream.Writable. As far as my interactions went, the two classes really weren't that different -- both had public write() methods which called internal _write() methods, and both shared the same method signatures.
When piped to a file, things got a little different. process.stdout and process.stderr were instances of a different class that wasn't immediately familiar. Best I can figure, it's a fs. SyncWriteStream, but that's a stab in the dark. Anyway, this class doesn't have a _write() method, so trying to override it was pointless.
The solution was to move one level higher and do my muting with write() instead of _write(). It does the same thing, and it does it consistently regardless of where the output is going.

Resources