diff --git a/src/autocomplete.ts b/src/autocomplete.ts index 18fa3be..d3f427e 100644 --- a/src/autocomplete.ts +++ b/src/autocomplete.ts @@ -6,6 +6,7 @@ import { bindClickOutside, findAll } from './utils/dom' import { bindInput } from './utils/input' import { History } from './history' import { Limiter, LimiterError } from './utils/limiter' +import { CancellableError } from './utils/promise' /** * @group Autocomplete @@ -44,22 +45,19 @@ export function autocomplete( return } - let lastRenderTime = Date.now() const input = bindInput(inputElement, { onInput: async (value) => { - const requestTime = Date.now() - try { await limiter.limited(() => { - return actions.updateState(value).then((state) => { - if (requestTime >= lastRenderTime) { + return actions.updateState(value).then( + (state) => { dropdown.update(state) } - }) + ) }) } catch (err) { - if (!(err instanceof LimiterError)) { + if (!(err instanceof LimiterError || err instanceof CancellableError)) { throw err } } @@ -165,7 +163,10 @@ function createInputDropdown({ return new Dropdown( dropdownElement, - actions.updateState(input.value), + actions.updateState(input.value).then( + (state) => state, + () => ({} as State), + ), config.render, config.submit, (value) => (input.value = value), diff --git a/src/state.ts b/src/state.ts index 652f688..b6b486b 100644 --- a/src/state.ts +++ b/src/state.ts @@ -83,14 +83,23 @@ export const getStateActions = ({ if (inputValue && inputValue.length >= minQueryLength) { cancellable = makeCancellable(fetchState(inputValue, config)) - return cancellable.promise + return cancellable.promise.then( + (s) => s as State, + (e) => { + throw e + }, + ) } else if (history) { return getHistoryState(inputValue ?? '') } return ( - cancellable?.promise ?? - AnyPromise.resolve({}).then((s) => s as State) + cancellable?.promise.then( + (s) => s as State, + (e) => { + throw e + }, + ) ?? AnyPromise.resolve({}).then((s) => s as State) ) }, addHistoryItem: (item: string) => { diff --git a/src/utils/promise.ts b/src/utils/promise.ts index 071ef21..58d3b39 100644 --- a/src/utils/promise.ts +++ b/src/utils/promise.ts @@ -84,16 +84,18 @@ export let AnyPromise = 'Promise' in window ? window.Promise : SimplePromise export type Cancellable = { promise: PromiseLike; cancel: () => void } +export class CancellableError extends Error {} + export function makeCancellable(promise: PromiseLike): Cancellable { let hasCanceled_ = false const wrappedPromise = new AnyPromise((resolve, reject) => { promise.then( (val) => { - hasCanceled_ ? reject({ isCanceled: true }) : resolve(val) + hasCanceled_ ? reject(new CancellableError('cancelled promise')) : resolve(val) }, (error) => { - hasCanceled_ ? reject({ isCanceled: true }) : reject(error) + hasCanceled_ ? reject(new CancellableError('cancelled promise')) : reject(error) }, ) })