Implement AbortSignal.timeout()
Categories
(Core :: DOM: Core & HTML, enhancement)
Tracking
()
Tracking | Status | |
---|---|---|
firefox100 | --- | fixed |
People
(Reporter: d, Assigned: saschanaz)
References
(Blocks 1 open bug)
Details
(Keywords: dev-doc-complete)
Attachments
(3 files)
Spec PR/mini-explainer (landed): https://github.com/whatwg/dom/pull/1032
Spec: https://dom.spec.whatwg.org/#dom-abortsignal-timeout
Web platform tests PR (landed): https://github.com/web-platform-tests/wpt/pull/32622
Comment 1•3 years ago
|
||
Comment 2•3 years ago
|
||
Landed on WebKit https://trac.webkit.org/changeset/289058/webkit
Comment 3•3 years ago
|
||
The implementation passes both https://wpt.live/dom/abort/AbortSignal.any.html and https://wpt.live/dom/abort/abort-signal-timeout.html. I am going to less active the next few weeks, so if this is urgent feel free to steal.
Comment 4•3 years ago
|
||
Bug 1734997 will probably use the timeout code too without any clamping.
Assignee | ||
Comment 5•3 years ago
|
||
Oh, I forgot to check this out. AFAICT the clamping can check TimeoutReason to not clamp for any new reasons.
Comment 6•3 years ago
|
||
sefeng is adding a flag to prevent clamping (for other reasons than this). Hopefully it can be reused.
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Updated•3 years ago
|
Assignee | ||
Comment 8•3 years ago
|
||
Assignee | ||
Comment 10•3 years ago
|
||
Comment 11•3 years ago
|
||
Comment 12•3 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/53d1dd2040d5
https://hg.mozilla.org/mozilla-central/rev/c9ed1172b434
https://hg.mozilla.org/mozilla-central/rev/111699477b1f
Comment 13•3 years ago
|
||
FF100 docs work for this can be tracked in https://github.com/mdn/content/issues/14641
Looking at the explainer the "more full example" shows handling for both a timeout abort and an abort signal triggered explicitly. Further down the document it seems to indicate that this is not actually possible - you can either timeout the signal or abort it but not both. Is that correct?
Does that mean that if you want to do both you still need to do the suggestion in https://github.com/whatwg/fetch/issues/951 ? :
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 5000)
const res = await fetch('https://example.com', { signal: controller.signal })
const body = await res.json()
clearTimeout(timeoutId)
If not, what is the recommended way to handle this case?
Reporter | ||
Comment 14•3 years ago
|
||
shows handling for both a timeout abort and an abort signal triggered explicitly.
That is not what the example shows. As it says in the comments, the "AbortError" case is for cases like the user pressing the stop button, or the page navigating away, or...
Comment 15•3 years ago
•
|
||
shows handling for both a timeout abort and an abort signal triggered explicitly.
That is not what the example shows. As it says in the comments, the "AbortError" case is for cases like the user pressing the stop button, or the page navigating away, or...
**I understand that the example "shows" how you might catch the "AbortError" but I don't see how that can be triggered since you don't have the controller. Specifically, AbortSignal.timeout()
returns an AbortSignal
and there is no way to get hold of the AbortController so you can call abort on that signal (from the stop button).
Further down your comment appear support this case "requires future work", because otherwise why would you need fetch to take multiple signals?
To spell it out in excruciating detail, this is your example, which looks like it can catch a TimeoutError
, AbortError
or something else. The fetch only takes the signal returned by AbortSignal.timeout()
. How would the code get a handle to the controller in order call abort on this?
try {
const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
const result = await res.text();
// ...
} catch (e) {
if (e.name === "TimeoutError") {
// It took more than 10 seconds to get the result!
} else if (e.name === "AbortError") {
// The fetch was explicitly aborted, e.g. by the user pressing the stop button!
} else {
// Something horrible went wrong, like a network error!
}
}
And then you say.
Future work: this feature would benefit greatly from a solution for combining AbortSignals, so that people could have an operation that aborts on either a timeout or an explicit abort. For example, something like this:
// NOT REAL CODE, YET: const controller = new AbortController(); fetch(url, { signal: AbortSignal.all([AbortSignal.timeout(10_000), controller.signal]) }); abortButton.onclick = () => controller.abort();
I hope this has explained my confusion enough that you can explain where I'm completely missing the point?
Reporter | ||
Comment 16•3 years ago
|
||
I understand that the example "shows" how you might catch the "AbortError" but I don't see how that can be triggered since you don't have the controller.
It can be triggered by the user pressing the stop button on their browser, which will cancel the fetch. The controller is not involved.
Comment 17•3 years ago
|
||
Thanks very much, it did not occur to me that browser chrome might also stop a download. I've updated the docs to reflect this.
Description
•