Memulai
Siklus Hidup
Peramban
Pengembangan
Paket Luar
useThrottleFn
Membatasi sebuah fungsi agar tidak jalan lebih sering dari sekali per jeda.
Ditekan: 0
Dijatah 1 detik: 0
Bedanya dengan debounce sering tertukar, jadi disebutkan di sini: debounce menunggu sampai panggilannya berhenti, throttle tetap jalan sepanjang panggilannya datang — cuma dijatah. Untuk pengetikan pakai debounce; untuk scroll, resize, dan pointermove pakai throttle.
Ditulis sendiri dengan alasan yang sama seperti useDebounceFn: nol dependensi, dan timernya ikut mati bersama scope-nya.
Pemasangan
npx shadcn-vue@latest add @kliping/use-throttle-fn Perlu @kliping terdaftar di components.json project Anda. Lihat cara menyiapkannya.
Tanpa dependensi — tidak ada berkas lain yang ikut terpasang.
Salin kode berikut ke project Anda.
ts
import { getCurrentScope, onScopeDispose, toValue } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
export interface UseThrottleFnOptions {
/** Jalankan panggilan pertama seketika. Bawaan: true. */
leading?: boolean
/** Jalankan panggilan terakhir setelah jedanya habis. Bawaan: true. */
trailing?: boolean
}
export function useThrottleFn<Fn extends (...args: any[]) => any>(
fn: Fn,
wait: MaybeRefOrGetter<number> = 1000,
options: UseThrottleFnOptions = {},
) {
const { leading = true, trailing = true } = options
let timer: ReturnType<typeof setTimeout> | undefined
let argumenTerakhir: Parameters<Fn> | undefined
let waktuJalanTerakhir = 0
const hentikanTimer = () => {
if (timer !== undefined) {
clearTimeout(timer)
timer = undefined
}
}
const cancel = () => {
hentikanTimer()
argumenTerakhir = undefined
waktuJalanTerakhir = 0
}
const flush = () => {
if (timer === undefined || !argumenTerakhir)
return
const argumen = argumenTerakhir
hentikanTimer()
argumenTerakhir = undefined
waktuJalanTerakhir = Date.now()
fn(...argumen)
}
const run = (...args: Parameters<Fn>) => {
const jeda = toValue(wait)
const sekarang = Date.now()
// `leading: false` diwujudkan dengan berpura-pura baru saja jalan, sehingga
// panggilan pertama ikut menunggu jatahnya seperti panggilan berikutnya.
if (waktuJalanTerakhir === 0 && !leading)
waktuJalanTerakhir = sekarang
const sisa = jeda - (sekarang - waktuJalanTerakhir)
argumenTerakhir = args
// `sisa > jeda` menjaga dari jam sistem yang mundur — tanpa itu, satu
// penyesuaian waktu bisa membekukan fungsinya sampai jamnya menyusul lagi.
if (sisa <= 0 || sisa > jeda) {
hentikanTimer()
waktuJalanTerakhir = sekarang
argumenTerakhir = undefined
fn(...args)
return
}
if (timer === undefined && trailing) {
timer = setTimeout(() => {
timer = undefined
waktuJalanTerakhir = leading ? Date.now() : 0
if (argumenTerakhir) {
const argumen = argumenTerakhir
argumenTerakhir = undefined
fn(...argumen)
}
}, sisa)
}
}
if (getCurrentScope())
onScopeDispose(cancel)
return { run, cancel, flush }
}API
ts
export interface UseThrottleFnOptions {
/** Jalankan panggilan pertama seketika. Bawaan: true. */
leading?: boolean
/** Jalankan panggilan terakhir setelah jedanya habis. Bawaan: true. */
trailing?: boolean
}
export function useThrottleFn<Fn extends (...args: any[]) => any>(
fn: Fn,
wait: MaybeRefOrGetter<number> = 1000,
options: UseThrottleFnOptions = {},
)