ðŸŠī\zansh.in\js

JavaScript tinkerings.

ðŸŒŋ identity functor / applicative / monad / maybe

Mathlessly journey from a basic Identity Functor to a Maybe Monad with an Applicative in-between.

Just(['world', 'hello'])
.map(x => x.reverse())
.map(x => x.join(', '))
.map(x => x + '!')
.valueOf()

🍂 finite state-machine

Banish status booleans (or derive them from something predictable) with a finite state-machine.

const { send, current } = StateMachine({
chart: {
idle: { REQUEST: 'loading' },
loading: { DONE: 'complete' }
},
onTransition: console.log
})
send('REQUEST')

message-bus

Use the existing browser events API to implement a message-bus.

on('update-store', () => {
console.log('store-updated!')
})
emit('update-store')

reducers / transducers / compose

Build a map and filter transducer little by little, compose them, and avoid talking about math.

const onlyIntegers = filter(isInteger)
const doubleNumbers = map(x => x * 2)
const addOne = map(x => x + 1)
;[1, 2, undefined, 3].reduce(
intoArray(
onlyIntegers,
doubleNumbers,
addOne
),
[]
)

cancelling promises

Three ways of cancelling promises: Using Revokable functions, Promises, and AbortController.

signal.addEventListener(
'abort',
() => {
reject(new Error('Cancelled'))
},
{ once: true }
)

pooling / limiting promises

Use Set to implement a Promise API that limits the number of concurrently running tasks.

const add = makePromisePool(2)
Promise.allSettled([
add(() => hold(3).then(log)),
add(() => hold(1).then(log)),
add(() => hold(2).then(log))
])

promise retrying

Take a function that creates a promise and retry it automatically if it fails. Memoize it to avoid duplicate instances.

const getUser = Memoize(
(id, invalidate) => {
const user = fetchWithRetries(3, id)
user.catch(invalidate)
return user
}
)

memoizer / caching / invalidation

If your function or promise is slow but predictable, wrap it in a memoizer to put it behind a cache.

const getValue = Memoize(
(key, invalidate) => {
setTimeout(invalidate, seconds(30))
return thisWillTakeAWhile(key)
}
)
const value = getValue(42)

debouncing / throttling

Treat repeated events happening across short periods of time as a single event with debouncing and throttling.

const [debounce, cancel] =
makeDebouncer(
seconds(1),
() => console.log('done')
)

array sorting callbacks

Create a factory that produces sorting functions you can apply to arrays of numbers or objects.

const numbers = [3, 2, 1]
.sort(ByNumber())
const objects =
[
{ id: 3, name: 'three' },
{ id: 2, name: 'two' },
{ id: 1, name: 'one' }
]
.sort(ByNumber('id'))

forEach / break / continue / @@iterator

Loops of the standard and functional variety, breaking out of them, and skipping iterations.

let count = 0
oneThousandItems().some((_, index) => {
if (index > 499) {
return true
}
count = count + 1
})