Skip to content

Instantly share code, notes, and snippets.

@aelindeman
Created October 13, 2022 19:49
Show Gist options
  • Save aelindeman/4229003caf6c64dc3c159e2aa1b3a241 to your computer and use it in GitHub Desktop.
Save aelindeman/4229003caf6c64dc3c159e2aa1b3a241 to your computer and use it in GitHub Desktop.
adds cancel behavior to ES6 Promises (e.g. for React components)

AbortablePromise

Adds cancel/abort functionality to Promises using an AbortController.

AbortController is available in all major browsers shipped after 2016 or later (except Safari; available after 2019).

Usage

const loadData = (): void => {
  // if already loading data, cancel that request, we have a new one!
  if (this.state.loading) {
    this.state.loading.abort('Replacing existing loadData request');
  }

  // make an AbortController and make it accessible in state
  const abortController = new AbortController();
  this.setState({ loading: abortController });

  // then just wrap the original Promise in AbortablePromise
  AbortablePromise(axios.get('http://example.com'), abortController)
    .then((data) => this.setState({ data }))
    .catch((error) => this.setState({ error })
    .finally(() => {
      // only clear the loading state if this same call was the one that set it
      if (this.state.loading == abortController) {
        this.setState({ loading: false });
      }
    });
};
export default <T>(promise: Promise<T>, ac: AbortController): Promise<T> => {
if (ac.signal.aborted) {
return Promise.reject(ac.signal);
}
return new Promise((resolve, reject) => {
ac.signal.addEventListener('abort', () => {
reject(ac.signal);
});
return Promise.resolve(promise).then(resolve).catch(reject);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment