Skip to content

xesam/js-fp-tools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

About

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

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors