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

js-fp-tools

v0.0.1

Published

控制异步函数行为的工具库,零依赖,支持微信小程序

Readme

js-fp-tools

控制异步函数行为的工具库。零依赖,支持微信小程序。

npm install js-fp-tools

函数一览

| 函数 | 解决什么问题 | |------|------------| | unique | 并发调用时只发一次请求,完成后重置 | | once | 只执行一次,后续调用返回缓存结果 | | last | 并发调用时只采纳最后一次的结果 | | serial | 并发调用排队,逐个执行 | | timeout | 超过时限则 reject | | attempt | 依次尝试多个函数,取第一个成功的结果 | | promisify | 将微信小程序 success/fail 回调转为 Promise |


unique

并发去重:请求在途时重复调用返回同一个 Promise,完成后重置。

适用场景:防止用户快速点击触发多次重复请求。

import { unique } from 'js-fp-tools'

const fetchUser = unique(async (id: string) => {
  const res = await fetch(`/api/user/${id}`)
  return res.json()
})

// 并发调用时只发一次请求
const [a, b] = await Promise.all([fetchUser('1'), fetchUser('1')])
// a === b,fetch 只调用了一次

// 完成后重置,下次调用重新发请求
const c = await fetchUser('1') // 重新发请求

once

单次执行:首次调用执行函数并缓存结果,后续调用直接返回缓存。

适用场景:初始化、鉴权 token 获取等只需执行一次的操作。

import { once } from 'js-fp-tools'

const getConfig = once(async () => {
  const res = await fetch('/api/config')
  return res.json()
})

await getConfig() // 发请求
await getConfig() // 直接返回缓存,不再发请求

// 失败后默认允许重试
const getToken = once(async () => { /* ... */ })
await getToken() // 失败
await getToken() // 重试

// 失败后不重试
const getToken2 = once(async () => { /* ... */ }, { retryOnFailure: false })

last

最后有效:并发调用时只 resolve 最后一次调用的结果,忽略前序结果。

适用场景:搜索建议、分页跳转等以最新结果为准的场景。

import { last } from 'js-fp-tools'

const search = last(async (keyword: string) => {
  const res = await fetch(`/api/search?q=${keyword}`)
  return res.json()
})

search('a')   // 发请求,结果被忽略
search('ab')  // 发请求,结果被忽略
search('abc') // 发请求,resolve 这次的结果

serial

串行化:并发调用排队,保证同时只有一个在执行。

适用场景:写操作、需要保证顺序的队列。

import { serial } from 'js-fp-tools'

const saveData = serial(async (data: object) => {
  await fetch('/api/save', { method: 'POST', body: JSON.stringify(data) })
})

// 并发调用按顺序执行,不会并发写入
saveData({ step: 1 })
saveData({ step: 2 })
saveData({ step: 3 })

timeout

超时控制:超过时限则 reject,原函数继续在后台运行。

import { timeout } from 'js-fp-tools'

const fetchWithTimeout = timeout(fetch, 5000)

try {
  const res = await fetchWithTimeout('/api/data')
} catch (err) {
  if ((err as any).code === 'TIMEOUT') {
    console.log('请求超时')
  }
}

attempt

降级链:依次尝试多个函数,返回第一个成功的结果;全部失败则 reject。

import { attempt } from 'js-fp-tools'

const getData = attempt(
  async () => fetchFromPrimary(),
  async () => fetchFromBackup(),
  async () => getCachedData(),
)

const data = await getData() // 主源失败则用备源,再失败则用缓存

promisify

将微信小程序 success/fail 回调风格的 API 转为 Promise。

import { promisify } from 'js-fp-tools'

// predict 返回 true 时直接调用原函数(如已有 success/fail 回调)
// predict 返回 false 时包装为 Promise
const request = promisify<wx.RequestOption>(
  (options) => !!(options.success || options.fail)
)(wx.request)

// 使用 Promise 风格
const res = await request({ url: '/api/data', method: 'GET' })

// 使用回调风格(透传)
request({
  url: '/api/data',
  success: (res) => console.log(res),
  fail: (err) => console.error(err),
})

License

MIT