Skip to content

Aborting a fetch: The Next Generation #447

Closed
@jakearchibald

Description

@jakearchibald

We were blocked on the resolution of cancelable promises, but consensus has broken down, so we need to find a new way.

How cancellation feels

startSpinner();

fetch(url).then(r => r.json()).then(data => {
  console.log(data);
}).catch(err => {
  if (err.name == 'AbortError') return;
  showErrorMessage();
}).finally(() => {
  stopSpinner();
});

(Hopefully finally will make it through TC39).

If we want reusable code with Node.js we might want to consider actually minting a non-DOMException for this.

The fetch controller

You can get a controller object for the fetch:

fetch(url, {
  control(controller) {
    // …
  }
});

The function name above is undecided.

This controller object will have methods to influence the in-progress fetch, such as abort. These methods will influence both the request and the response stream.

Aborting an already aborted fetch will be a no-op, but there will be ways to query the final state of the fetch.

Other than the above, the design of the API is undecided.

The fetch observer

There will be an component that allows the developer to observe the progress of the fetch. This includes changes to priority, progress, final state (complete, cancelled, error etc). This component will include async getters for current state.

The observable component should use addEventListener rather than observables. We don't want a TC39 dependency, and true observables are likely to be compatible with addEventListener. We should be careful with the naming of this observer as a result.

It's undecided how you'll get this object when calling fetch. The controller may extend it, the controller may have it as a property, or the two objects may be offered independently.

Other than the above, the design of the API is undecided.

Controlling multiple fetches at once

It should be relatively easy to cancel three fetches at once, or change their priority at the same time. If this is complicated to do in a low-level way, we may consider ways of creating a single controller that can be provided to multiple fetches, or a way to allow a controller to mimic another fetch through its observer.

How this happens is undecided.

Within a service worker

The observer component will be available to a fetch event via a property.

addEventListener('fetch', event => {
  console.log(event.fetchObserver);
});

The property name above is undecided.

This should allow the service worker to hear about the page's intentions with the fetch in regards to priority and cancellation, and perform the same on the fetches it creates.

It seems unlikely that event.respondWith(fetch(event.request)) would give you any of this for free.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions