UNPKG

petite-utils

Version:

A collection of small util function in JavaScript.

116 lines (109 loc) 2.89 kB
/* * @Author : ZhouQiJun * @Date : 2024-10-28 01:04:56 * @LastEditors : ZhouQiJun * @LastEditTime: 2025-03-22 21:40:58 * @Description : repeatRun 函数 - 重复执行函数 * 解决 setInterval 时间不精确的问题 */ import { isFunction, isNumber } from '../type/type' /** * @description: stop run repeat-function */ export type StopRepeat = () => void export type RepeatFn = ( repeatTimes: number, stop: StopRepeat, params?: unknown, ) => void export interface RepeatOptions { interval?: number immediate?: boolean } /** * ## repeat call function * @group 工具函数 * @param fn will be called repeatly * @param param1.interval interval time default 1000 * @param param1.immediate call fn immediately default false * @param params params pass to fn * @returns stopFunction to stop repeat * @example * ### pass a arrow function to repeat * ```ts * repeatRun((repeatTimes, stop) => { * console.log(repeatTimes) * if (repeatTimes === 5) { * stop() // stop function from fn params * } * }) * ``` * @example * ### pass a function definition to repeat and stop it by repeat return value * ```ts * let stop = repeatRun(sayHi, { interval: 1000 }) * function sayHi(repeatTimes) { * console.log(repeatTimes) * if (repeatTimes === 5) { * stop() // stop from repeatRun return value * } * } * ``` */ export function repeatRun( fn: RepeatFn, { interval = 1000, immediate = false }: RepeatOptions = {}, params?: unknown, ): StopRepeat { if (!isFunction(fn)) { throw new Error('first argument must be a function') } if (!isNumber(interval) || interval <= 0) { throw new Error('interval must be a positive number') } const stop: StopRepeat = () => { hasStopped = true clearTimeout(timer) clearTimeout(timer2) } let hasStopped = false let timer2 let repeatTimes = 0 if (immediate) { ++repeatTimes fn(repeatTimes, stop, params) } let timer = setTimeout(function repeat() { if (hasStopped) { return } ++repeatTimes fn(repeatTimes, stop, params) timer2 = setTimeout(repeat, interval) }, interval) return stop } // 函数定义和函数表达式的区别 // 函数定义会被提升,var 的函数表达式不会被提升,let const 的函数表达式不会被提升 // let stop = repeat(hello) // // this is ok, because function definition is hoisted // function hello(_, times) { // console.log('hello', times) // if (times === 10) { // stop() // } // } // // this is not ok, because var initialization is hoisted ❌ // var hello = function (_, time) { // console.log('hello', times) // if (times === 10) { // stop() // } // } // // this is not ok, because let and const variable are not hoisted ❌ // let hello = (_, time) => { // console.log('hello', times) // if (times === 10) { // stop() // } // }