A collection of useful functions for JavaScript developers.
- runParallel
- retry
- timelog
- tryParseJSON
- wait
- groupBy
- lazyInit
- ensureModule
- existCmd
- calcHash
- calcFileHash
function runParallel<T, U>(
data: T[],
mapper: (v: T, i: number) => Promise<U>,
concurrency?: number
): Promise<U[]>
Run promises in parallel with a concurrency limit and return the results in the same order.
import {wait} from '@musicq/toolbox'
const res = await runParallel([40, 20, 50, 10], wait, 2)
// res => [40, 20, 50, 10]
If you don't specify a concurrency limit, it will default to run all promises in parallel.
You can run promises sequentially by setting the concurrency limit to 1.
Retry a promise function with max retry times and delay(ms).
function retry<T>(
fn: () => Promise<T>,
maxRetryTimes: number,
delay: number
): Promise<T>
const fn = () => new Promise((resolve, reject) => reject(1))
await retry(fn, 3, 0)
// throw 1
Log the execution time of a function.
function timelog<T>(
log: string,
fn: () => Promise<T>,
hideStartLog?: boolean
): Promise<T>
function timelog<T>(log: string, fn: () => T, hideStartLog?: boolean): T
timelog('parse json', () => JSON.parse('{"name": "@musicq/toolbox"}'))
//=> [parse json] starting...
//=> [parse json]: 1.021ms
await timelog('fetch google', () => fetch('https://google.com'))
//=> [fetch google] starting...
//=> [fetch google]: 100.123ms
You can hide the starting log by passing true
as the third argument.
await timelog('fetch google', () => fetch('https://google.com'), true)
//=> [fetch google]: 100.123ms
Try to parse a JSON string with a ergonomic API.
function tryParseJSON<T>(source: string): Result<T>
const json = tryParseJSON('{a: 1}') // {ok: false, error: SyntaxError: Unexpected token a in JSON at position 1}
if (!json.ok) {
console.error(json.error)
return
}
console.log(json.value)
tryParseJSON('{"a": 1}')
// {ok: true, value: {a: 1}}
Wait for a number of milliseconds.
function wait<T>(ms: number, fn?: () => T): Promise<T>
await wait(10)
await wait(10, () => 'something')
Group an array by a key.
function groupBy<S, V>(
source: S[],
keySelector: (v: S) => string,
elementSelector?: (v: S) => V
): Record<string, V[]>
const source = [
{name: 'a', value: 1},
{name: 'b', value: 2},
{name: 'a', value: 3},
{name: 'b', value: 4},
]
const result = groupBy(
source,
x => x.name,
x => x.value
)
// {a: [1, 3], b: [2, 4]}
Lazy init variables.
This is useful when some variables might not been initialized yet when it was declared.
function lazy<T>(a: () => T): {unwrap: () => T}
const lazyVariable = lazy(() => 1)
const unwrappedValue = lazyVariable.unwrap()
//=> 1
Ensure a module is loaded and cached.
This is useful when you want to load a ESM module from a CJS module.
function ensureModule<M>(moduleName: string): Promise<M>
// index.cjs
import fetch from 'node-fetch'
// this will throw an error
// index.ts
const fetch = await ensureModule<typeof import('node-fetch')>('node-fetch')
// this will work
Check if a command exists in the current environment.
function existCmd(cmd: string): boolean
if (existCmd('zip')) {
console.log('zip exists')
} else {
console.log(' does not exist')
}
Calculate hash of a buffer or string using the given algorithm.
Default algorithm is md5
.
function calcHash(buffer: BinaryLike, algorithm?: string): string
calcHash('something')
// 437b930db84b8079c2dd804a71936b5f
calcHash('something', 'sha256')
// 3fc9b689459d738f8c88a3a48aa9e33542016b7a4052e001aaa536fca74813cb
Calculate hash of a file using the given algorithm.
Default algorithm is md5
.
function calcFileHash(
filepath: string,
algorithm?: string
): Promise<Result<string, Error>>
import fs from 'fs'
await fs.promises.writeFile('example.txt', 'something')
await calcFileHash('example.txt')
// {ok: true, value: '437b930db84b8079c2dd804a71936b5f'}