crypto = window.crypto || window.msCrypto // for IE 11
window.crypto.getRandomValues will fill an array (its only argument) of typed integers (using classes like Uint8Array, Uint16Array, etc. for 8- or 16-bit unsigned integers). The integers will be random in the range allowed for the specified type. So larger-sized integers give you more granularity, though the randomness should not be affected by size. You can then map that range to the range of values you're interested in, the same way you'd map a random floating point number between 0 and 1 to a range of values.
Unlike the old Math.random function, window.crypto.getRandomValues uses your underlying OS's entropy for seeding randomness. This entropy is something an outside attacker should not be able to have any control over, relative to browser-only entropy.
windowobject is not in the Node runtime at all. Thus you need to grab an npm module (
npm install get-random-values) if you want to be able to use one isomorphic (i.e. the same code will work in Node or in browser) call to generate random numbers in any environment.
But for pure Node.js, you can use Node's builtin crypto: crypto.randomBytes. This is Node, so the call can optionally/possibly be asynchronous. Why? It's possible for a system to run out of entropy and thus be blocked for a tiny amount of time (should not be more than a second) to gather more entropy from various hardware sources. Generating millions of random numbers could exhaust OS entropy. A single call should return immediately, though. Also note that Node's crypto.randomBytes returns a variable-length byte string whereas window.crypto.getRandomValues modifies in place the integer values in a given array where the integers can be from 8 to 64 bits.