mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
refactor(editor): replace debounce and throttle with lodash (#10639)
This commit is contained in:
@@ -26,7 +26,9 @@
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^10.0.1",
|
||||
"yjs": "^13.6.21",
|
||||
"zod": "^3.23.8"
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { BlockSelection } from '@blocksuite/block-std';
|
||||
import { Bound } from '@blocksuite/global/gfx';
|
||||
import { throttle } from '@blocksuite/global/utils';
|
||||
import { Text } from '@blocksuite/store';
|
||||
import { computed } from '@preact/signals-core';
|
||||
import { html, nothing } from 'lit';
|
||||
@@ -36,6 +35,7 @@ import { property, queryAsync, state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { when } from 'lit/directives/when.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { EmbedBlockComponent } from '../common/embed-block-element.js';
|
||||
|
||||
@@ -4,10 +4,11 @@ import {
|
||||
isGfxBlockComponent,
|
||||
ShadowlessElement,
|
||||
} from '@blocksuite/block-std';
|
||||
import { throttle, WithDisposable } from '@blocksuite/global/utils';
|
||||
import { WithDisposable } from '@blocksuite/global/utils';
|
||||
import { html, nothing } from 'lit';
|
||||
import { property, queryAsync } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import {
|
||||
RENDER_CARD_THROTTLE_MS,
|
||||
|
||||
@@ -8,15 +8,12 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { Bound, deserializeXYWH } from '@blocksuite/global/gfx';
|
||||
import {
|
||||
debounce,
|
||||
DisposableGroup,
|
||||
WithDisposable,
|
||||
} from '@blocksuite/global/utils';
|
||||
import { DisposableGroup, WithDisposable } from '@blocksuite/global/utils';
|
||||
import { type Query, type Store } from '@blocksuite/store';
|
||||
import { css, html, nothing, type PropertyValues } from 'lit';
|
||||
import { property, query, state } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
|
||||
import type { EdgelessRootPreviewBlockComponent } from '../../edgeless-root-preview-block.js';
|
||||
|
||||
@@ -182,7 +179,9 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
||||
this._clearFrameDisposables();
|
||||
this._frameDisposables = new DisposableGroup();
|
||||
this._frameDisposables.add(
|
||||
frame.propsUpdated.on(debounce(this._updateFrameViewportWH, 10))
|
||||
frame.propsUpdated.on(
|
||||
debounce(this._updateFrameViewportWH, 10, { leading: true })
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { property } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
|
||||
function TransparentIcon(hollowCircle = false) {
|
||||
const CircleIcon: TemplateResult | typeof nothing = hollowCircle
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { stopPropagation } from '@blocksuite/affine-shared/utils';
|
||||
import { WidgetComponent } from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { debounce, Slot } from '@blocksuite/global/utils';
|
||||
import { Slot } from '@blocksuite/global/utils';
|
||||
import {
|
||||
ArrowLeftSmallIcon,
|
||||
ArrowRightSmallIcon,
|
||||
@@ -29,6 +29,7 @@ import { baseTheme, cssVar } from '@toeverything/theme';
|
||||
import { css, html, nothing, unsafeCSS } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
import { cache } from 'lit/directives/cache.js';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js';
|
||||
import type { MenuPopper } from './common/create-popper.js';
|
||||
@@ -233,36 +234,40 @@ export class EdgelessToolbarWidget extends WidgetComponent<
|
||||
@state()
|
||||
accessor containerWidth = 1920;
|
||||
|
||||
private readonly _onContainerResize = debounce(({ w }: { w: number }) => {
|
||||
if (!this.isConnected) return;
|
||||
private readonly _onContainerResize = debounce(
|
||||
({ w }: { w: number }) => {
|
||||
if (!this.isConnected) return;
|
||||
|
||||
this.slots.resize.emit({ w, h: TOOLBAR_HEIGHT });
|
||||
this.containerWidth = w;
|
||||
this.slots.resize.emit({ w, h: TOOLBAR_HEIGHT });
|
||||
this.containerWidth = w;
|
||||
|
||||
if (this._denseSeniorTools) {
|
||||
this.scrollSeniorToolIndex = Math.min(
|
||||
this._seniorTools.length - this.scrollSeniorToolSize,
|
||||
this.scrollSeniorToolIndex
|
||||
);
|
||||
} else {
|
||||
this.scrollSeniorToolIndex = 0;
|
||||
}
|
||||
if (this._denseSeniorTools) {
|
||||
this.scrollSeniorToolIndex = Math.min(
|
||||
this._seniorTools.length - this.scrollSeniorToolSize,
|
||||
this.scrollSeniorToolIndex
|
||||
);
|
||||
} else {
|
||||
this.scrollSeniorToolIndex = 0;
|
||||
}
|
||||
|
||||
if (
|
||||
this._denseQuickTools &&
|
||||
this._moreQuickToolsMenu &&
|
||||
this._moreQuickToolsMenuRef
|
||||
) {
|
||||
this._moreQuickToolsMenu.close();
|
||||
this._openMoreQuickToolsMenu({
|
||||
currentTarget: this._moreQuickToolsMenuRef,
|
||||
});
|
||||
}
|
||||
if (!this._denseQuickTools && this._moreQuickToolsMenu) {
|
||||
this._moreQuickToolsMenu.close();
|
||||
this._moreQuickToolsMenu = null;
|
||||
}
|
||||
}, 300);
|
||||
if (
|
||||
this._denseQuickTools &&
|
||||
this._moreQuickToolsMenu &&
|
||||
this._moreQuickToolsMenuRef
|
||||
) {
|
||||
this._moreQuickToolsMenu.close();
|
||||
this._openMoreQuickToolsMenu({
|
||||
currentTarget: this._moreQuickToolsMenuRef,
|
||||
});
|
||||
}
|
||||
if (!this._denseQuickTools && this._moreQuickToolsMenu) {
|
||||
this._moreQuickToolsMenu.close();
|
||||
this._moreQuickToolsMenu = null;
|
||||
}
|
||||
},
|
||||
300,
|
||||
{ leading: true }
|
||||
);
|
||||
|
||||
private _resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
|
||||
@@ -12,16 +12,13 @@ import {
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { PropTypes, requiredProperties } from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import {
|
||||
SignalWatcher,
|
||||
throttle,
|
||||
WithDisposable,
|
||||
} from '@blocksuite/global/utils';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils';
|
||||
import { MoreHorizontalIcon } from '@blocksuite/icons/lit';
|
||||
import { effect } from '@preact/signals-core';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { property, query, queryAll, state } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import { getPopperPosition } from '../../utils/position.js';
|
||||
import type { LinkedDocContext, LinkedMenuGroup } from './config.js';
|
||||
|
||||
@@ -4,12 +4,9 @@ import {
|
||||
} from '@blocksuite/affine-components/rich-text';
|
||||
import type { UIEventStateContext } from '@blocksuite/block-std';
|
||||
import { TextSelection, WidgetComponent } from '@blocksuite/block-std';
|
||||
import {
|
||||
assertType,
|
||||
debounce,
|
||||
DisposableGroup,
|
||||
} from '@blocksuite/global/utils';
|
||||
import { assertType, DisposableGroup } from '@blocksuite/global/utils';
|
||||
import { InlineEditor } from '@blocksuite/inline';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
|
||||
import type { RootBlockComponent } from '../../types.js';
|
||||
import {
|
||||
@@ -75,7 +72,8 @@ const showSlashMenu = debounce(
|
||||
container.append(slashMenu);
|
||||
return slashMenu;
|
||||
},
|
||||
100
|
||||
100,
|
||||
{ leading: true }
|
||||
);
|
||||
|
||||
export const AFFINE_SLASH_MENU_WIDGET = 'affine-slash-menu-widget';
|
||||
|
||||
@@ -13,12 +13,13 @@ import {
|
||||
isFuzzyMatch,
|
||||
substringMatchScore,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { throttle, WithDisposable } from '@blocksuite/global/utils';
|
||||
import { WithDisposable } from '@blocksuite/global/utils';
|
||||
import { autoPlacement, offset } from '@floating-ui/dom';
|
||||
import { html, LitElement, nothing, type PropertyValues } from 'lit';
|
||||
import { property, state } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import { getPopperPosition } from '../../utils/position.js';
|
||||
import type {
|
||||
|
||||
@@ -26,13 +26,15 @@
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"collapse-white-space": "^2.1.0",
|
||||
"date-fns": "^4.0.0",
|
||||
"katex": "^0.16.11",
|
||||
"lit": "^3.2.0",
|
||||
"lit-html": "^3.2.1",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"remark-math": "^6.0.0",
|
||||
"shiki": "^3.0.0",
|
||||
"yjs": "^13.6.21",
|
||||
@@ -69,9 +71,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/lodash.clonedeep": "^4.5.9"
|
||||
},
|
||||
"version": "0.20.0"
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ import { SurfaceBlockModel } from '@blocksuite/block-std/gfx';
|
||||
import { createIdentifier } from '@blocksuite/global/di';
|
||||
import type { IVec } from '@blocksuite/global/gfx';
|
||||
import { Point } from '@blocksuite/global/gfx';
|
||||
import { throttle } from '@blocksuite/global/utils';
|
||||
import type { BlockModel, ExtensionType } from '@blocksuite/store';
|
||||
import { computed, signal } from '@preact/signals-core';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import { DropIndicator } from './drop-indicator';
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"dompurify": "^3.2.4",
|
||||
"fractional-indexing": "^3.2.0",
|
||||
"lit": "^3.2.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.mergewith": "^4.6.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mdast-util-gfm-autolink-literal": "^2.0.1",
|
||||
"mdast-util-gfm-footnote": "^2.0.0",
|
||||
"mdast-util-gfm-strikethrough": "^2.0.0",
|
||||
@@ -72,8 +72,6 @@
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/lodash.clonedeep": "^4.5.9",
|
||||
"@types/lodash.mergewith": "^4",
|
||||
"vitest": "3.0.7"
|
||||
},
|
||||
"version": "0.20.0"
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
Slot,
|
||||
} from '@blocksuite/global/utils';
|
||||
import { computed, type Signal, signal } from '@preact/signals-core';
|
||||
import clonedeep from 'lodash.clonedeep';
|
||||
import mergeWith from 'lodash.mergewith';
|
||||
import clonedeep from 'lodash-es/cloneDeep';
|
||||
import mergeWith from 'lodash-es/mergeWith';
|
||||
import * as Y from 'yjs';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ReferenceInfo } from '@blocksuite/affine-model';
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
import cloneDeep from 'lodash-es/cloneDeep';
|
||||
|
||||
/**
|
||||
* Clones reference info.
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
type GfxViewportElement,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import type { Container, ServiceIdentifier } from '@blocksuite/global/di';
|
||||
import { debounce, DisposableGroup } from '@blocksuite/global/utils';
|
||||
import { DisposableGroup } from '@blocksuite/global/utils';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
|
||||
import {
|
||||
debugLog,
|
||||
@@ -144,13 +145,9 @@ export class ViewportTurboRendererExtension extends LifeCycleWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
debouncedRefresh = debounce(
|
||||
() => {
|
||||
this.refresh().catch(console.error);
|
||||
},
|
||||
debounceTime,
|
||||
{ leading: false, trailing: true }
|
||||
);
|
||||
debouncedRefresh = debounce(() => {
|
||||
this.refresh().catch(console.error);
|
||||
}, debounceTime);
|
||||
|
||||
invalidate() {
|
||||
this.layoutVersion++;
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^10.0.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { Point } from '@blocksuite/global/gfx';
|
||||
import { throttle } from '@blocksuite/global/utils';
|
||||
import { computed } from '@preact/signals-core';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import {
|
||||
DRAG_HANDLE_CONTAINER_WIDTH,
|
||||
@@ -34,6 +34,8 @@ import {
|
||||
* Used to control the drag handle visibility in page mode
|
||||
*/
|
||||
export class PointerEventWatcher {
|
||||
private _isPointerDown = false;
|
||||
|
||||
private get _gfx() {
|
||||
return this.widget.std.get(GfxControllerIdentifier);
|
||||
}
|
||||
@@ -220,6 +222,7 @@ export class PointerEventWatcher {
|
||||
|
||||
private readonly _throttledPointerMoveHandler = throttle<UIEventHandler>(
|
||||
ctx => {
|
||||
if (this._isPointerDown) return;
|
||||
if (
|
||||
this.widget.doc.readonly ||
|
||||
this.widget.dragging ||
|
||||
@@ -231,6 +234,10 @@ export class PointerEventWatcher {
|
||||
if (this.widget.isGfxDragHandleVisible) return;
|
||||
|
||||
const state = ctx.get('pointerState');
|
||||
|
||||
// When pointer is moving, should do nothing
|
||||
if (state.delta.x !== 0 && state.delta.y !== 0) return;
|
||||
|
||||
const { target } = state.raw;
|
||||
const element = captureEventTarget(target);
|
||||
// When pointer not on block or on dragging, should do nothing
|
||||
@@ -330,6 +337,14 @@ export class PointerEventWatcher {
|
||||
}
|
||||
};
|
||||
|
||||
private readonly _pointerDownHandler: UIEventHandler = () => {
|
||||
this._isPointerDown = true;
|
||||
};
|
||||
|
||||
private readonly _pointerUpHandler: UIEventHandler = () => {
|
||||
this._isPointerDown = false;
|
||||
};
|
||||
|
||||
constructor(readonly widget: AffineDragHandleWidget) {}
|
||||
|
||||
reset() {
|
||||
@@ -341,5 +356,7 @@ export class PointerEventWatcher {
|
||||
this.widget.handleEvent('click', this._clickHandler);
|
||||
this.widget.handleEvent('pointerMove', this._throttledPointerMoveHandler);
|
||||
this.widget.handleEvent('pointerOut', this._pointerOutHandler);
|
||||
this.widget.handleEvent('pointerDown', this._pointerDownHandler);
|
||||
this.widget.handleEvent('pointerUp', this._pointerUpHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
"@blocksuite/icons": "^2.2.3",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"lit": "^3.2.0"
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
|
||||
@@ -15,12 +15,12 @@ import {
|
||||
WidgetComponent,
|
||||
} from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { throttle } from '@blocksuite/global/utils';
|
||||
import type { BaseSelection, UserInfo } from '@blocksuite/store';
|
||||
import { computed, effect } from '@preact/signals-core';
|
||||
import { css, html, nothing, type PropertyValues } from 'lit';
|
||||
import { state } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import { RemoteColorManager } from '../manager/remote-color-manager';
|
||||
import type { DocRemoteSelectionConfig } from './config';
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"dompurify": "^3.2.4",
|
||||
"fractional-indexing": "^3.2.0",
|
||||
"lib0": "^0.2.97",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lz-string": "^1.5.0",
|
||||
"rehype-parse": "^9.0.0",
|
||||
"unified": "^11.0.5",
|
||||
|
||||
@@ -5,8 +5,9 @@ import {
|
||||
type IVec,
|
||||
Vec,
|
||||
} from '@blocksuite/global/gfx';
|
||||
import { debounce, Slot } from '@blocksuite/global/utils';
|
||||
import { Slot } from '@blocksuite/global/utils';
|
||||
import { signal } from '@preact/signals-core';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
|
||||
import type { GfxViewportElement } from '.';
|
||||
|
||||
@@ -73,21 +74,13 @@ export class Viewport {
|
||||
|
||||
ZOOM_MIN = ZOOM_MIN;
|
||||
|
||||
private readonly _resetZooming = debounce(
|
||||
() => {
|
||||
this.zooming$.value = false;
|
||||
},
|
||||
200,
|
||||
{ leading: false, trailing: true }
|
||||
);
|
||||
private readonly _resetZooming = debounce(() => {
|
||||
this.zooming$.value = false;
|
||||
}, 200);
|
||||
|
||||
private readonly _resetPanning = debounce(
|
||||
() => {
|
||||
this.panning$.value = false;
|
||||
},
|
||||
200,
|
||||
{ leading: false, trailing: true }
|
||||
);
|
||||
private readonly _resetPanning = debounce(() => {
|
||||
this.panning$.value = false;
|
||||
}, 200);
|
||||
|
||||
constructor() {
|
||||
this.elementReady.once(el => (this._element = el));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { throttle } from '@blocksuite/global/utils';
|
||||
import type { BaseSelection, BlockModel } from '@blocksuite/store';
|
||||
import throttle from 'lodash-es/throttle';
|
||||
|
||||
import { TextSelection } from '../selection/index.js';
|
||||
import type { BlockComponent } from '../view/element/block-component.js';
|
||||
@@ -7,7 +7,6 @@ import { BLOCK_ID_ATTR } from '../view/index.js';
|
||||
import { isActiveInEditor } from './active.js';
|
||||
import { RANGE_SYNC_EXCLUDE_ATTR } from './consts.js';
|
||||
import type { RangeManager } from './range-manager.js';
|
||||
|
||||
/**
|
||||
* Two-way binding between native range and text selection
|
||||
*/
|
||||
|
||||
@@ -23,96 +23,6 @@ export function noop(_?: unknown) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @example
|
||||
* ```ts
|
||||
* const log = (message: string) => console.log(`[${new Date().toISOString()}] ${message}`);
|
||||
*
|
||||
* const throttledLog = throttle(log, 1000);
|
||||
*
|
||||
* throttledLog("Hello, world!");
|
||||
* throttledLog("Hello, world!");
|
||||
* throttledLog("Hello, world!");
|
||||
* throttledLog("Hello, world!");
|
||||
* throttledLog("Hello, world!");
|
||||
* ```
|
||||
*/
|
||||
|
||||
export function throttle<T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
limit: number,
|
||||
options?: { leading?: boolean; trailing?: boolean }
|
||||
): T;
|
||||
export function throttle<
|
||||
Args extends unknown[],
|
||||
T extends (...args: Args) => void,
|
||||
>(
|
||||
fn: (...args: Args) => void,
|
||||
limit: number,
|
||||
options?: { leading?: boolean; trailing?: boolean }
|
||||
): T;
|
||||
export function throttle<
|
||||
Args extends unknown[],
|
||||
T extends (this: unknown, ...args: Args) => void,
|
||||
>(fn: T, limit: number, { leading = true, trailing = true } = {}): T {
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
let lastArgs: Args | null = null;
|
||||
|
||||
const setTimer = () => {
|
||||
if (lastArgs && trailing) {
|
||||
fn(...lastArgs);
|
||||
lastArgs = null;
|
||||
timer = setTimeout(setTimer, limit);
|
||||
} else {
|
||||
timer = null;
|
||||
}
|
||||
};
|
||||
|
||||
return function (this: unknown, ...args: Parameters<T>) {
|
||||
if (timer) {
|
||||
// in throttle
|
||||
lastArgs = args;
|
||||
return;
|
||||
}
|
||||
// Execute the function on the leading edge
|
||||
if (leading) {
|
||||
fn.apply(this, args);
|
||||
}
|
||||
timer = setTimeout(setTimer, limit);
|
||||
} as T;
|
||||
}
|
||||
|
||||
export const debounce = <T extends (...args: any[]) => void>(
|
||||
fn: T,
|
||||
limit: number,
|
||||
{ leading = true, trailing = true } = {}
|
||||
): T => {
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
let lastArgs: Parameters<T> | null = null;
|
||||
|
||||
// eslint-disable-next-line sonarjs/no-identical-functions
|
||||
const setTimer = () => {
|
||||
if (lastArgs && trailing) {
|
||||
fn(...lastArgs);
|
||||
lastArgs = null;
|
||||
timer = setTimeout(setTimer, limit);
|
||||
} else {
|
||||
timer = null;
|
||||
}
|
||||
};
|
||||
|
||||
return function (...args: Parameters<T>) {
|
||||
if (timer) {
|
||||
lastArgs = args;
|
||||
clearTimeout(timer);
|
||||
}
|
||||
if (leading && !timer) {
|
||||
fn(...args);
|
||||
}
|
||||
timer = setTimeout(setTimer, limit);
|
||||
} as T;
|
||||
};
|
||||
|
||||
export async function nextTick() {
|
||||
// @ts-expect-error check window.scheduler
|
||||
if ('scheduler' in window && 'yield' in window.scheduler) {
|
||||
|
||||
Reference in New Issue
Block a user