Errors in function, but the function works - why? - node.js

I have a function that generates a random filename in the format "greetingXX.gif" where "XX" is a number between 1 and 20. See code below:
1 function getGIF(callback) {
2 let randomGIF;
3 let gifName = "greeting";
4 const GIF_EXTENSION = ".gif";
5 const MAX_GREETING = 20;
6 randomGIF = Math.floor(Math.random() * MAX_GREETING) + 1;
7 if (randomGIF < 10) {
8 gifName += "0" + randomGIF;
9 } else {
10 gifName += randomGIF;
11 }
12 gifName += GIF_EXTENSION;
13 callback(gifName);
14 }
The function works, BUT in WebStorm I get the following warnings:
Unused Variable randomGIF (Line 2)
Unused constant MAX_GREETING (Line 5)
Element MAX_GREETING is not imported (Line 6)
Variable gifName might not have been initialised (Line 8 and Line 10)
Like I say, the function does exactly what it is supposed to do. But why am I getting these warnings? And more specifically, how do I change my code so I don't get them?

I was able to fix this by invalidating caches (File | Invalidate caches, Invalidate and restart). Thanks to lena for this!

Related

How to convert 24 hour format to 12 hour format in groovy [duplicate]

This question already has answers here:
How to convert 24 hr format time in to 12 hr Format?
(16 answers)
Closed 3 years ago.
I'm new to groovy and i want to convert 24 hour format to 12 hour format. What is the code to be used for it? Is there any built-in methods?
I just want groovy code not java one
Kevin's answer is correct, and should get the tick... I only post this as it's slightly shorter
import java.time.*
import static java.time.format.DateTimeFormatter.ofPattern
String time = '13:23:45'
String result = LocalTime.parse(time).format(ofPattern('h:mm:ss a'))
println result
I thought this question is somewhat similar to the How to convert 24 hr format time in to 12 hr Format?. It just that Java and Groovy share a lot of similarities. To point that out, I took Cloud's answer from the mentioned question and converted that to Groovy.
import java.time.LocalTime
import java.time.format.DateTimeFormatter
final String time = "21:49"
String result = LocalTime.parse(time, DateTimeFormatter.ofPattern("HH:mm")).format(DateTimeFormatter.ofPattern("hh:mm a"));
println(result)
If you want to build your own time function you can try to customize the code below.
final String time = "21:49"
final String _24to12( final String input ){
if ( input.indexOf(":") == -1 )
throw ("")
final String []temp = input.split(":")
if ( temp.size() != 2 )
throw ("") // Add your throw code
// This does not support time string with seconds
int h = temp[0] as int // if h or m is not a number then exception
int m = temp[1] as int // java.lang.NumberFormatException will be raised
// that can be cached or just terminate the program
String dn
if ( h < 0 || h > 23 )
throw("") // add your own throw code
// hour can't be less than 0 or larger than 24
if ( m < 0 || m > 59 )
throw("") // add your own throw code
// minutes can't be less than 0 or larger than 60
if ( h == 0 ){
h = 12
dn = "AM"
} else if ( h == 12 ) {
dn = "PM"
} else if ( h > 12 ) {
h = h - 12
dn = "PM"
} else {
dn = "AM"
}
return h.toString() + ":" + m.toString() + " " + dn.toString()
}
println(_24to12(time))

Nested for loops start at wrong numbers

I am trying to use a nested for loop to create x and y coordinates for a method call. However, console.log shows that the loop variables are starting at the wrong value. Why is this? Here is my code:
for(let x = 0; x < 64; x++) {
console.log(x);
for(let y = 0; y < 32; y++) {
console.log(y);
}
}
This prints:
22
23
24
25
26
27
28
29
30
31
34
0
1
2
3
4
5
6
7
8
[values 9 - 30 omitted]
31
34
1
...and so on
Are you sure? I have tested this with node v8.9.1 and the code works for me as expected:
The outer loop starts at index 0 which gets printed on the console,
then the inner loop prints numbers 0 to 31.
In turn the outer loop continues at index 1 which gets printed on console and
then the inner loop prints 0 to 31,
and so on
May be you got confused with the output at some point. Thus, my suggestion is to prefix the console outputs with x and y as shown below.
for(let x = 0; x < 64; x++) {
console.log('x=' + x);
for(let y = 0; y < 32; y++) {
console.log('y=' + y);
}
}
You can also trial this on repl.it
I can tell you with relative confidence that the behaviour your print is describing is not the behaviour a for-loop of the kind you've written will yield.
In fact, copy-pasting your exact code to the Chrome console (which runs V8, the same as node) will yield the correct result:
Your issue lies either elsewhere in your code or in the tool you're looking at the logging in.

How to read/write a bigint from buffer in node.js 10?

I see that BigInt is supported in node 10. However, there's no ReadBigInt() functionality in the Buffer class.
Is it possible to somehow go around it? Perhaps read 2 ints, cast them to BigInt, shift the upper one and add them to reconstruct the bigint?
A little late to the party here, but as the BigInt ctor accepts a hex string we can just convert the Buffer to a hex string and pass that in to the BigInt ctor. This also works for numbers > 2 ** 64 and doesn't require any dependencies.
function bufferToBigInt(buffer, start = 0, end = buffer.length) {
const bufferAsHexString = buffer.slice(start, end).toString("hex");
return BigInt(`0x${bufferAsHexString}`};
}
I recently had encountered the need to do this as well, and managed to find this npm library: https://github.com/no2chem/bigint-buffer ( https://www.npmjs.org/package/bigint-buffer ) which can read from a buffer as a BigInt.
Example Usage (reading, there is more examples on the linked github/npm):
const BigIntBuffer = require('bigint-buffer');
let testBuffer = Buffer.alloc(16);
testBuffer[0] = 0xff; // 255
console.log(BigIntBuffer.toBigIntBE(testBuffer));
// -> 338953138925153547590470800371487866880n
That will read the 16byte (128bit) number from the buffer.
If you wish to read only part of it as a BigInt, then slicing the buffer should work.
With Node v12, functions for reading bigint from buffers was added, so if possible, you should try to use Node v12 or later.
But these functions are just pure math based on reading integers from the buffer, so you can pretty much copy them into your Node 10-11 code.
https://github.com/nodejs/node/blob/v12.6.0/lib/internal/buffer.js#L78-L152
So modifying these methods to not be class methods could look something like this
function readBigUInt64LE(buffer, offset = 0) {
const first = buffer[offset];
const last = buffer[offset + 7];
if (first === undefined || last === undefined) {
throw new Error('Out of bounds');
}
const lo = first +
buffer[++offset] * 2 ** 8 +
buffer[++offset] * 2 ** 16 +
buffer[++offset] * 2 ** 24;
const hi = buffer[++offset] +
buffer[++offset] * 2 ** 8 +
buffer[++offset] * 2 ** 16 +
last * 2 ** 24;
return BigInt(lo) + (BigInt(hi) << 32n);
}
EDIT: For anyone else having the same issue, I created a package for this.
https://www.npmjs.com/package/read-bigint
One liner: BigInt('0x'+buffer.toString('hex'))

ReadStream skipping bytes?

I'm writing a keyboard-events parser for Linux, using node.js. It's working somewhat okay, but sometimes it seems like node is skipping a few bytes. I'm using a ReadStream to get the data, handle it, process it, and eventually output it when a separator character is encountered (in my case, \n).
Here is the part of my class that handles the read data:
// This method is called through this callback:
// this.readStream = fs.createReadStream(this.path);
// this.readStream.on("data", function(a) { self.parse_data(self, a); });
EventParser.prototype.parse_data = function(self, data)
{
/*
* Data format :
* {
* 0x00 : struct timeval time { long sec (8), long usec (8) } (8 bytes)
* 0x08 : __u16 type (2 bytes)
* 0x10 : __u16 code (2 bytes)
* 0x12 : __s32 value (4 bytes)
* } = (16 bytes)
*/
var dataBuffer = new Buffer(data);
var slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
while (dataBuffer.length > 0 && slicedBuffer.length == 16)
{
var type = GetDataType(slicedBuffer),
code = GetDataCode(slicedBuffer),
value = GetDataValue(slicedBuffer);
if (type == CST.EV.KEY)
{ // Key was pressed: KEY event type
if (code == 42 && value == 1) { self.shift_pressed = true; }
if (code == 42 && value == 0) { self.shift_pressed = false; }
console.log(type + "\t" + code + "\t" + value + "\t(" + GetKey(self.shift_pressed, code) + ")")
// GetKey uses a static array to get the actual character
// based on whether the shift key is held or not
if (value == 1)
self.handle_processed_data(GetKey(self.shift_pressed, code));
// handle_processed_data adds characters together, and outputs the string when encountering a
// separator character (in this case, '\n')
}
// Take a new slice, and loop.
slicedBuffer = dataBuffer.slice(0, 16);
dataBuffer = dataBuffer.slice(16, dataBuffer.length);
}
}
// My system is in little endian!
function GetDataType(dataBuffer) { return dataBuffer.readUInt16LE(8); }
function GetDataCode(dataBuffer) { return dataBuffer.readUInt16LE(10); }
function GetDataValue(dataBuffer) { return dataBuffer.readInt32LE(12); }
I'm basically filling up the data structure explained at the top using a Buffer. The interesting part is the console.log near the end, which will print everything interesting (related to the KEY event) that passes in our callback! Here is the result of such log, complete with the expected result, and the actual result:
EventParserConstructor: Listening to /dev/input/event19
/* Expected result: CODE-128 */
/* Note that value 42 is the SHIFT key */
1 42 1 ()
1 46 1 (C)
1 42 0 ()
1 46 0 (c)
1 42 1 ()
1 24 1 (O)
1 42 0 ()
1 24 0 (o)
1 42 1 ()
1 32 1 (D)
1 42 0 ()
1 32 0 (d)
1 42 1 ()
1 18 1 (E)
1 42 0 ()
1 18 0 (e)
1 12 0 (-)
1 2 0 (1)
1 3 1 (2)
1 3 0 (2)
1 9 1 (8)
1 9 0 (8)
1 28 1 (
)
[EventParser_Handler]/event_parser.handle_processed_data: CODE28
/* Actual result: CODE28 */
/* The '-' and '1' events can be seen in the logs, but only */
/* as key RELEASED (value: 0), not key PRESSED */
We can clearly see the - and 1 character events passing by, but only as key releases (value: 0), not key presses. The weirdest thing is that most of the time, the events are correctly translated. But 10% of the time, this happens.
Is ReadStream eating up some bytes, occasionally? If yes, what alternative should I be using?
Thanks in advance!
Well, turns out that my loop was rotten.
I was assuming that the data would only come in chunks of 16 bytes... Which obviously isn't always the case. So sometimes, I had packets of <16 bytes being left over and lost between two 'data' event callbacks.
I added this by adding an excessBuffer field to my class and using it to fill my initial slicedBuffer when receiving data.

What is exactly happening when I am using setTimeout within another function and trying to print the value of the argument passed?

I was going through learnyounode when I had to complete the juggling async challenge, and that is where I came across a similar simpler problem as below:
// try print numbers 0 - 9
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
}
the above snippet gives the output as:
10
10
10
10
10
10
10
10
10
10
which is not the intended result, however when I write it in the following way:
// try print numbers 0 - 9
var f = function(i) {
setTimeout(function() {
console.log(i)
})
}
for (var i = 0; i < 10; i++)f(i);
I get the desired output. So what is exactly happening when I am writing the setTimeout() portion inside that function?
In the first snipped, i variable is defined outside the function. You can access it just simply because it is on its (higher level) scope and there isn't another i variable defined in the function own (or any intermediate if it had been exist).
The for loop sets ten timeouts (enqueued to the event loop). But they will be executed only when the for loop had finished, so i value is 10 (the last of the iteration).
In the second example, you are surrounding the setTimeout() inside a closure (function) which is execued immediately each loop iteration.
In those iterations, when the function is called, the current value of i is passed as parameter (also named i, which is defined in the local function's scope and, because it has the same name, hides the fact you aren't calling the same variable).
See below slight modification of your second example:
// try print numbers 0 - 9
var f = function(j) {
setTimeout(function() {
console.log(i, j)
})
}
for (var i = 0; i < 10; i++)f(i);
// Output:
// -------
// 10 0
// 10 1
// 10 2
// 10 3
// 10 4
// 10 5
// 10 6
// 10 7
// 10 8
// 10 9
This is because variable declared with var is function-level, not block-level.
The first snippt is same code below
```
var i;
// try print numbers 0 - 9
for (i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i)
})
}
all 'i's point to same address in memory which eventually equal 10.
When it comes to second snippt,because you pass i as an parameter into a function, the real value of i will copy to new memory address in stack for the function. Each i in the function point to the new memory address with diffent value.

Resources