浏览代码

Change Regulator to RateLimiter and export Debouncer, Throttler, and RateLimiter (abstract class).

Afshin T. Darian 6 年之前
父节点
当前提交
6f250660c1
共有 3 个文件被更改,包括 81 次插入69 次删除
  1. 1 1
      packages/coreutils/src/index.ts
  2. 80 0
      packages/coreutils/src/ratelimiter.ts
  3. 0 68
      packages/coreutils/src/regulator.ts

+ 1 - 1
packages/coreutils/src/index.ts

@@ -9,7 +9,7 @@ export * from './nbformat';
 export * from './pageconfig';
 export * from './path';
 export * from './poll';
-export * from './regulator';
+export * from './ratelimiter';
 export * from './settingregistry';
 export * from './statedb';
 export * from './text';

+ 80 - 0
packages/coreutils/src/ratelimiter.ts

@@ -0,0 +1,80 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { IRateLimiter } from './interfaces';
+
+import { Poll } from './poll';
+
+/**
+ * A base class to implement rate limiters with different invocation strategies.
+ */
+export abstract class RateLimiter implements IRateLimiter {
+  /**
+   * Instantiate a rate limiter.
+   *
+   * @param fn - The function to rate limit.
+   *
+   * @param limit - The rate limit; defaults to 500ms.
+   */
+  constructor(fn: () => any, limit = 500) {
+    this.limit = limit;
+    this.poll = new Poll({
+      factory: async () => await fn(),
+      frequency: { backoff: false, interval: Poll.NEVER, max: Poll.NEVER },
+      standby: 'never'
+    });
+    void this.poll.stop();
+  }
+
+  /**
+   * The rate limit in milliseconds.
+   */
+  readonly limit: number;
+
+  /**
+   * Invoke the rate limited function.
+   */
+  abstract async invoke(): Promise<void>;
+
+  /**
+   * Stop the function if it is mid-flight.
+   */
+  async stop(): Promise<void> {
+    return this.poll.stop();
+  }
+
+  /**
+   * The underlying poll instance used by the rate limiter.
+   */
+  protected poll: Poll<void, void, 'invoked'>;
+}
+
+/**
+ * Wraps and debounces a function that can be called multiple times and only
+ * executes the underlying function one `interval` after the last invocation.
+ *
+ * @param fn - The function to debounce.
+ *
+ * @param interval - The debounce interval; defaults to 500ms.
+ */
+export class Debouncer extends RateLimiter {
+  async invoke(): Promise<void> {
+    return this.poll.schedule({ interval: this.limit, phase: 'invoked' });
+  }
+}
+
+/**
+ * Wraps and throttles a function that can be called multiple times and only
+ * executes the underlying function once per `interval`.
+ *
+ * @param fn - The function to throttle.
+ *
+ * @param interval - The throttle interval; defaults to 500ms.
+ */
+export class Throttler extends RateLimiter {
+  async invoke(): Promise<void> {
+    if (this.poll.state.phase !== 'invoked') {
+      return this.poll.schedule({ interval: this.limit, phase: 'invoked' });
+    }
+  }
+}

+ 0 - 68
packages/coreutils/src/regulator.ts

@@ -1,68 +0,0 @@
-// Copyright (c) Jupyter Development Team.
-// Distributed under the terms of the Modified BSD License.
-
-import { Poll } from './poll';
-
-interface IRegulator {
-  invoke(): Promise<void>;
-  stop(): Promise<void>;
-}
-
-export type Debounced = IRegulator;
-
-export type Throttled = IRegulator;
-
-class Regulator extends Poll<void, void, 'invoked'> {
-  constructor(options: {
-    factory: Poll.Factory<void, void, 'invoked'>;
-    constraints: { interval: number; strategy: 'debounce' | 'throttle' };
-  }) {
-    super({ factory: options.factory });
-    this.constraints = options.constraints;
-    this.frequency = { backoff: false, interval: Poll.NEVER, max: Poll.NEVER };
-    this.standby = 'never';
-    void super.stop();
-  }
-
-  readonly constraints: { interval: number; strategy: 'debounce' | 'throttle' };
-
-  async invoke(): Promise<void> {
-    const { interval, strategy } = this.constraints;
-    if (strategy === 'debounce') {
-      return this.schedule({ interval, phase: 'invoked' });
-    }
-    if (this.state.phase !== 'invoked') {
-      return this.schedule({ interval, phase: 'invoked' });
-    }
-  }
-}
-
-/**
- * Returns a debounced function that can be called multiple times and only
- * executes the underlying function one `interval` after the last invocation.
- *
- * @param fn - The function to debounce.
- *
- * @param interval - The debounce interval; defaults to 500ms.
- */
-export function debounce(fn: () => any, interval = 500): Debounced {
-  return new Regulator({
-    factory: async () => await fn(),
-    constraints: { interval, strategy: 'debounce' }
-  });
-}
-
-/**
- * Returns a throttled function that can be called multiple times and only
- * executes the underlying function once per `interval`.
- *
- * @param fn - The function to throttle.
- *
- * @param interval - The throttle interval; defaults to 500ms.
- */
-export function throttle(fn: () => any, interval = 500): Throttled {
-  return new Regulator({
-    factory: async () => await fn(),
-    constraints: { interval, strategy: 'throttle' }
-  });
-}