-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support abort API #592
Merged
Merged
Support abort API #592
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
93e9cec
Support abort API
jamesplease 53565c1
Support abort without replacing native fetch
jamesplease 9a7d232
Remove event listener; use request.signal
jamesplease fd5c261
Skip creation of XHR if signal is already aborted
jamesplease 318e95f
First pass at documentation
jamesplease 0e1b651
More tweaks based on feedback
jamesplease d47f6c9
Remove some semicolons
jamesplease 529c9fa
Add `signal` property to Request instead of Response
mislav 8ba0cdb
Polyfill DOMException if missing
mislav 074c89e
Polyfill DOMException
mislav b832229
Add tests for aborting requests
mislav c6aff30
Avoid creating XMLHttpRequest if we're immediately aborting
mislav d9aa590
Clear event listener for all xhr completion status.
joaovieira 886a076
Merge pull request #1 from joaovieira/abort-polyfill
joaovieira 9f9a00f
Test signal reuse. Add AbortSignal polyfill.
joaovieira bab0f3d
Consistent implementation of EventTarget as in MDN.
joaovieira 0bed2ba
Split EventTarget and AbortSignal polyfills.
joaovieira 66ed8ba
Merge pull request #2 from joaovieira/abort-polyfill
joaovieira 738d51a
Add tests with signal within Request object.
joaovieira 8f778f3
Fix EventTarget callback invocation context.
joaovieira f0e24f8
Native EventTarget is not inheritable.
joaovieira 36bf692
Replace AbortSignal polyfill with abortcontroller-polyfill module.
joaovieira 7f6b8d2
Upgrade abortcontroller-polyfill.
joaovieira c31fca9
Merge remote-tracking branch 'origin/master' into abort-polyfill
mislav f035860
Scope abortcontroller to polyfill only
mislav 2bd7f22
Export DOMException for `instanceof` checks
mislav c873843
Polish documentation for aborting requests
mislav File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -443,6 +443,10 @@ | |
reject(new TypeError('Network request failed')) | ||
} | ||
|
||
xhr.onabort = function() { | ||
reject(new DOMException('Aborted', 'AbortError')) | ||
} | ||
|
||
xhr.open(request.method, request.url, true) | ||
|
||
if (request.credentials === 'include') { | ||
|
@@ -459,6 +463,10 @@ | |
xhr.setRequestHeader(name, value) | ||
}) | ||
|
||
if (init.signal && init.signal.addEventListener) { | ||
init.signal.addEventListener('abort', xhr.abort) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we remove the event listener also in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup. I'll do that. |
||
} | ||
|
||
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit) | ||
}) | ||
} | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to attach
onabort
callback? The promise can be rejected withinabortXhr()
just as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mislav I believe this is the most correct as mentioned here. Calling abort on the XHR will set the right status code and
readyState
(https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with
xhr.abort()
. I'm just saying that we don't need to install thexhr.onabort
callback just to reject the promise. We know thatabortXhr()
will be executed, so we can reject the promise in there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.. xhr is never exposed so it can't be aborted from the outside. Is there any other way it could be aborted (e.g. by the browser)? If not, there shouldn't be any difference. I don't mind this way though, reads well :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onabort
wasn't needed until now, and since we control literally the only place from which the xhr is aborted, I don't think adding one level of indirection on top ofabortXhr
is necessary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't
onAbort()
also confirm thatxhr.abort()
was successful vs. just trusting the results ofabortXhr()
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dysonpro That's correct, but we aren't interested in whether
xhr.abort()
was performed successfully or not. We want to reject the promise right away because we know for sure an abort was requested.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mislav for your explanation. I am excited about this functionality so I have been following this PR carefully. I am already using this branch code in a project that requires aborting no longer needed requests.
Your point is that you want to ensure the promise is rejected, correct? I feel that it is closer to the core intention of the PR (and my own project as well) to ensure that the abort was completed successfully. Is there a way to do that without utilizing the
xhr.onAbort()
callback? Without that I feel that there could be a gap in the verification of the functionality for every platform and environment. Thanks again for your feedback.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dysonpro Your concerns are valid, but we have different priorities when thinking about this. At the point when
abortXhr()
is invoked (which can only happen upon AbortSignal), I consider the request most definitely discarded. We can then callxhr.abort(); reject(...)
all at once. Now, if there is a browser which would somehow fail to actually abort the XHR whenxhr.abort()
is called, and thus never invokeonabort
callback, that is fine with me because we already ensured that the promise is rejected. I don't expect this case to happen often (or ever, for that matter) and so I'm not concerned with it. I also don't expectonabort
happening without us explicitly requesting it (after all, it wasn't needed until now). The code change that I suggested, when all is said and done, is mostly stylistic.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are rather obscure use cases, but they're real nonetheless. I think a general
fetch
polyfill should handle these, so it should listen forxhr.onabort
.There's nothing wrong with immediately rejecting after calling
xhr.abort()
, but it should also reject fromxhr.onabort
.