npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

phunky

v2.0.0

Published

Funky promise-based cached thunk

Readme

phunky

npm package npm downloads

phunky (promisified thunk, pronounced funky) is yet another thunk-inspired library, to delay a calculation until its result is needed, but also cache the result

:star: You can provide a max age for the cache, so it automatically resolves your function again when stale, or force a new value at any time

:tada: You can customise the behaviour of your Phunk, perhaps immediately resolve, or choose to cache rejections, very funky!

:goat: Being promise-based, you can await the result of your function inline

:100: Test coverage

Getting started

Importing

// Only ESM is supported
import { Phunk } from 'phunky'

Example usage

import { Phunk } from 'phunky'

let counter = 0

const getNextCounter = async () => {
  counter += 1
  return counter
}

const counterCache = new Phunk(getNextCounter)

console.log(await counterCache.current()) // 1
console.log(await counterCache.current()) // 1
console.log(await counterCache.next()) // 2
console.log(await counterCache.next()) // 3
console.log(await counterCache.current()) // 3

Cache auto-refresh

Setting a ttl (time-to-live) will allow your function to automatically be re-invoked if the value is considered stale. Great for caching access tokens, or any values that can be time-expensive to refresh on every operation.

let counter = 0

const getNextCounter = async () => {
  counter += 1
  return counter
}

const counterCache = new Phunk(getNextCounter, { ttl: 1000 })

console.log(await counterCache.current()) // 1
// wait at least 1 second
console.log(await counterCache.current()) // 2

Resolution status

If you have a long-running function to execute, you can always inspect the status using the following helper methods

  • isResolving will return true if your function is running
  • isResolved will return true if your function completed without throwing
  • isRejected will return true if your function threw an error
const myThunk = new Phunk(async () => { /* Some long process */ })

myThunk.next() // if you don't await the result then:
console.log(myThunk.isResolving()) // true
console.log(myThunk.isResolved()) // false
console.log(myThunk.isRejected()) // false

Configuration

Optionally pass a configuration object as a second argument to the constructor, with the following options

  • init: Optional, defaults to false, set to true to immediately invoke your function and have the result ready for when you first call .current().
  • initialValue: Optional. If set, your Phunk instance will resolve this value until either you call .next() or the tll duration has elapsed. Note, this option is redundant if you set init to true.
  • allowUndefinedInitialValue: Optional, defaults to false, set to true if you want to manually set an initialValue of undefined, otherwise only defined values will be used.
  • cacheRejections: Optional, defaults to false, set to true for your Phunky instance to cache any errors that are thrown by your function. If false, calling .current() will try re-invoking your function if it previously rejected.
  • ttl: (time-to-live) Optional. If set, it must be a positive integer for the number of milliseconds resolved values should live for. Any calls to .current() after that time, will automatically re-invoke your function to get an updated value.
  • stale: Optional. A callback that takes the current resolved value as an argument to manually check if that value should be considered stale. The callback should return true if stale. This will cause your Phunk to automatically resolve a new value.

Class methods

  • current(): Returns a promise of the result of the previous invocation of your function, or will await the result of the next invocation of your function if it has not previously been invoked or other criteria are met, see cacheRejections and ttl config options.
  • next(): Returns a promise of the result of the next invocation of your function.
  • isResolving(): Returns a boolean of whether your function is currently being invoked.
  • isResolved(): Returns a boolean of whether your function previously resolved without error. Will always return false if isResolving() returns true.
  • isRejected(): Returns a boolean of whether your function previously rejected with an error. Will always return false if isResolving() returns true.