js

A 18-post collection

Javascript Seedable Random for reproducibility

I would never understand the seed of seedable random functions, if not from the academics background or with testing in mind.

In academics, it is important for the results to be reproducable so that other people could test and review it and have the same results as you do (brag).

With testing in mind, you would find it hard to test functions with random behavior it just doesn't work well with the unit testing and simple assertions. With seedable random functions you can seed it with the same seed during test, and you will get the exact-same-predictable results every time.

Unfortunately, Math.random() doesn't support this.

From Mozilla (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random), I quote:

The Math.random() function returns a floating-point, pseudo-random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive), which you can then scale to your desired range. The implementation selects the initial seed to the random number generation algorithm; it cannot be chosen or reset by the user.

Luckily, you have an alternative Math.ramdom(), here https://github.com/davidbau/seedrandom.

Usage: (took from the repo)

Math.seedrandom('hello.');  
console.log(Math.random());          // Always 0.9282578795792454  
console.log(Math.random());          // Always 0.3752569768646784  
อ่านต่อ »

Properly Stop Node Listener

Here is a listener on process object:

process.on('unhandledRejection', (err) => {  
    console.error(err)
})

And, a way to remove the listener is:

process.removeListenter(<name>, <function>)  

Note that, you have to specify both its name and function because for each name there can be many functions that listen.

So, inpractice, I think it is much easier to manage listeners if we use it this way:

function listen(obj, name, func) {  
    const on = obj['on']
    const removeListener = obj['removeListener']
    if (typeof on !== 'function'
        || typeof removeListener !== 'function') {
        throw new Error('object is not listenable')
    }
    on(name, func)
    return () => { removeListener(name, func) }
}

Usage:

const remover = litsen(process, 'unhandledRejection', (err) => console.error(err))  
# to stop listening
remover()  
อ่านต่อ »

Run Node as a Background Service and Starts on Startup (Windows)

Ever wonder how to make your node application works as a background process and has a nice easy to use management interface ?

Wouldn't be great if you can register your node app as a one of the Services in Windows ?

There is a package just for you ! node-windows, just install it right now !

I prefer the local installation way, which is npm install --save node-windows, note that in the official instalation they will guite you to install with -g flag.

Now, as a forerunner in this, I will kinda guide you through this ... which is quite easy though...

Let's assume that your service can be run in this fashion node index.js arg1 arg2, it's reasonable to assume that your program have some arguments.

As far as I know, I found not a way to include arguments in the usage of node-windows, may be I just didn't look thorough enough, in the source code. However, in this example I will assume that we have a file (or files) run.ts that will run node index.js args1 args2 for us.

You can imagine run.ts to look like.

import child_process = require('child_process')  
child_process.execSync('node index.js arg1 arg2')  

So far so good right ? It's kinda work but not exactly favorable ... one thing you have to make sure is that whenever the run.ts got killed, esp. by SIGINT (ctrl + c) which is the way Windows Services manager will use to stop your service, the run.ts will always relay this signal to its child.

I think execSync is not preferable anymore considering this matter. I rather use spawn instead.

import child_process = require('child_process')  
function signal(proc, signal, cb: (code, signal) => void) {  
    proc.on('close', (code, signal) => {
        cb(code, signal)
    })
    proc.kill(signal)
อ่านต่อ »

Node Mysql Multiple Statements

If you happen to use npm install mysql or the native mysql connetion libary for node. You might encounter with my problem.

Something like, sql syntax error with queries containing ; (semi-colon), to join many quries to one request. I didn't know that this is forbidden by default and I need to specifically enable it with a flag.

Here is the flag:

var connection = mysql.createConnection({multipleStatements: true})  

Maybe it is default to prevent the sql injection ? may be... ?

อ่านต่อ »

RegEx to tokenize command line commands

Regex:

/'[^']+'|"[^"]+"|[^\s"]+/g

So, in javascript (typescript):

function tokenize(command: string): string[] {  
    return command.match(/'[^']+'|"[^"]+"|[^\s"]+/g)
}

Note: /g is global match

If the command line is as follows:

test 'parsing this string' -e yeah "wow wow"  

Using the code above will give us this:

test  
'parsing this string'  
-e
yeah  
"wow wow"
อ่านต่อ »

To Deal With NodeJS Unhandled Promise Rejection Warning

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2):  

This happens when you have promise but forget to .catch() it.

In my case, I tend to forget this with async functions, like:

async function test() {  
    ....
}

test() // this can cause the unhandled promise rejection  

You can do it globally this way.

process.on('unhandledRejection', (err) => { ... })  

I don't think it's a good idea to rely on this process.on(..), becasue you have to make sure that you .then().catch() your promises correctly in the first place.

อ่านต่อ »

JS: Do not use .map() with fn(...args)

Okay, you might say "of course not!", well I just didn't know T_T

The definition of Array.prototype.map() is, according to Mozilla:

var new_array = arr.map(callback[, thisArg])  

Where callback is: callback(currentValue, index, array)

Yes! despite the fact that we usually use [1,2,3].map((x) => ...), utterly careless about the 2nd and 3rd arguments. It's still there, javascript just automagically ignores them.

Note: those who're so familiar with Python might, like I do, feel the map callback function should have only one argument.

Now, when we combine it with javascript's spread syntax hell begins:

function p(...words) {  
    return `<p>${words.join(' ')}</p>`
}

const words = [  
    'Hello', 'world!', 'it', 'works!'
]
words.map(p)  

Here is the results:

[ '<p>Hello 0 Hello,world!,it,works!</p>',
  '<p>world! 1 Hello,world!,it,works!</p>',
  '<p>it 2 Hello,world!,it,works!</p>',
  '<p>works! 3 Hello,world!,it,works!</p>' ]

It just doesn't work as you might expect as I didn't expect this!

อ่านต่อ »