控制异步函数行为的工具库。零依赖,支持微信小程序。
npm install js-fp-tools| 函数 | 解决什么问题 |
|---|---|
unique |
并发调用时只发一次请求,完成后重置 |
once |
只执行一次,后续调用返回缓存结果 |
last |
并发调用时只采纳最后一次的结果 |
serial |
并发调用排队,逐个执行 |
timeout |
超过时限则 reject |
attempt |
依次尝试多个函数,取第一个成功的结果 |
promisify |
将微信小程序 success/fail 回调转为 Promise |
并发去重:请求在途时重复调用返回同一个 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') // 重新发请求单次执行:首次调用执行函数并缓存结果,后续调用直接返回缓存。
适用场景:初始化、鉴权 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 })最后有效:并发调用时只 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 这次的结果串行化:并发调用排队,保证同时只有一个在执行。
适用场景:写操作、需要保证顺序的队列。
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 })超时控制:超过时限则 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('请求超时')
}
}降级链:依次尝试多个函数,返回第一个成功的结果;全部失败则 reject。
import { attempt } from 'js-fp-tools'
const getData = attempt(
async () => fetchFromPrimary(),
async () => fetchFromBackup(),
async () => getCachedData(),
)
const data = await getData() // 主源失败则用备源,再失败则用缓存将微信小程序 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),
})MIT