| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- /**
- * A disposable object
- */
- export interface IDisposable {
- /** 释放进程 */
- dispose(): void
- }
-
- /**
- * Execute the callback the next time the browser is idle, returning an
- * {@link IDisposable} that will cancel the callback when disposed. This wraps
- * [requestIdleCallback] so it will fallback to [setTimeout] if the environment
- * doesn't support it.
- *
- * @param callback The callback to run when idle, this includes an
- * [IdleDeadline] that provides the time alloted for the idle callback by the
- * browser. Not respecting this deadline will result in a degraded user
- * experience.
- * @param timeout A timeout at which point to queue no longer wait for an idle
- * callback but queue it on the regular event loop (like setTimeout). Typically
- * this should not be used.
- *
- * [IdleDeadline]: https://developer.mozilla.org/en-US/docs/Web/API/IdleDeadline
- * [requestIdleCallback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
- * [setTimeout]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout
- */
- export let runWhenIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable
-
- declare function requestIdleCallback(
- callback: (args: IdleDeadline) => void,
- options?: { timeout: number },
- ): number
- declare function cancelIdleCallback(handle: number): void
-
- if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
- runWhenIdle = (runner) => {
- setTimeout(() => {
- if (disposed) {
- return
- }
- const end = Date.now() + 15 // one frame at 64fps
- runner(
- Object.freeze({
- didTimeout: true,
- timeRemaining() {
- return Math.max(0, end - Date.now())
- },
- }),
- )
- })
- let disposed = false
- return {
- dispose() {
- if (disposed) {
- return
- }
- disposed = true
- },
- }
- }
- } else {
- runWhenIdle = (runner, timeout?) => {
- const handle: number = requestIdleCallback(
- runner,
- typeof timeout === 'number' ? { timeout } : undefined,
- )
- let disposed = false
- return {
- dispose() {
- if (disposed) {
- return
- }
- disposed = true
- cancelIdleCallback(handle)
- },
- }
- }
- }
-
- /**
- * An implementation of the "idle-until-urgent"-strategy as introduced
- * 将计算过程推迟到浏览器空闲时运行,这可以避免在浏览器不空闲时执行计算操作,从而提高页面性能。
- * here: https://philipwalton.com/articles/idle-until-urgent/
- */
- export class IdleValue<T> {
- private readonly _executor: () => void
- private readonly _handle: IDisposable
-
- private _didRun = false
- private _value?: T
- private _error: unknown
-
- constructor(executor: () => T) {
- this._executor = () => {
- try {
- this._value = executor()
- } catch (err) {
- this._error = err
- } finally {
- this._didRun = true
- }
- }
- this._handle = runWhenIdle(() => this._executor())
- }
-
- /** 用于释放该对象 */
- dispose(): void {
- this._handle.dispose()
- }
-
- /** 用于获取计算后的值 */
- get value(): T {
- if (!this._didRun) {
- this._handle.dispose()
- this._executor()
- }
- if (this._error) {
- throw this._error
- }
- return this._value!
- }
-
- /** 用于检查该对象的值是否已经初始化过 */
- get isInitialized(): boolean {
- return this._didRun
- }
- }
-
- //#endregion
-
|