WIP: Add a mechanism to fetch to track progress#1843
WIP: Add a mechanism to fetch to track progress#1843lukewarlow wants to merge 4 commits intowhatwg:mainfrom
Conversation
fetch.bs
Outdated
| </ol> | ||
| </div> | ||
|
|
||
| TEMPORARY <dfn id=event-fetchobserver-progress event for=FetchObserver><code>progress</code></dfn> |
There was a problem hiding this comment.
Need to define the event somewhere properly. (potentially taking the event definitions from XHR?)
| <a for="fetch controller">process the next manual redirect</a> for <a for=/>requests</a> with | ||
| <a for=request>redirect mode</a> set to "<code>manual</code>". | ||
|
|
||
| <h2 id=interface-progressevent>Interface {{ProgressEvent}}</h2> |
There was a problem hiding this comment.
This is taken from XHR and should be removed from XHR in a corresponding PR.
|
|
||
| <h3 id=firing-events-using-the-progressevent-interface>Firing events using the {{ProgressEvent}} interface</h3> | ||
|
|
||
| <p>To <dfn id=concept-event-fire-progress>fire a progress event</dfn> named <var>e</var> at |
There was a problem hiding this comment.
Should fetch really fire sync events? It would match XHR but I wonder if these should be queued instead?
|
|
||
| <p><em>This section is non-normative.</em> | ||
|
|
||
| <p>The suggested {{Event/type}} |
There was a problem hiding this comment.
Most of these events aren't used in Fetch so this table should probably be kept in the XHR spec.
| </ol> | ||
|
|
||
| <li> | ||
| <p>Let <var>processResponse</var> given a <var>response</var> be these steps: |
There was a problem hiding this comment.
If we want to do progress tracking for response we'll need to do it differently to XHR, XHR consumes the body inside of this algorithm but fetch obviously can't.
One idea is to wrap response's body with a wrapper readable stream that allows use to fire progress events when the body actually gets read. This way we don't consume anything to report progress, (we can make it so we only wrapper if there's a responseObserver with a progress event listeners).
There was a problem hiding this comment.
There was a problem hiding this comment.
Essentially because there's no access to it from within the JS fetch() definition.
fetch.bs
Outdated
| FetchObserverCallback observer; | ||
| }; | ||
|
|
||
| callback FetchObserverCallback = undefined (FetchObserver requestObserver, FetchObserver responseObserver); |
There was a problem hiding this comment.
Firefox has the below IDL. I split it so the observers still fire events named progress but it's maybe fine to keep it as a single eventtarget and just change the event names?
[Exposed=Window]
callback interface ObserverCallback {
undefined handleEvent(FetchObserver observer);
};
enum FetchState {
// Pending states
"requesting", "responding",
// Final states
"aborted", "errored", "complete"
};
[Exposed=(Window,Worker),
Pref="dom.fetchObserver.enabled"]
interface FetchObserver : EventTarget {
readonly attribute FetchState state;
// Events
attribute EventHandler onstatechange;
attribute EventHandler onrequestprogress;
attribute EventHandler onresponseprogress;
};
fetch.bs
Outdated
| https://github.com/whatwg/dom/issues/1031#issuecomment-1233206400 --> | ||
| </ol> | ||
|
|
||
| <li><p>Let <var>hasUploadListeners</var> be false. |
There was a problem hiding this comment.
Should probably be hasRequestListeners
|
An alternative design that could be considered is to just make Request and event target and fire progress events at the request object directly. Would require authors to construct a request attach a listener and then pass to fetch but might be okay? |
|
@lukewarlow I wonder if that could get confusing in cases where request/response isn't used in a fetch. Eg, if we made these things transferrable/clonable, would you expect progress events when getting a |
|
Yeah that's a good point. Perhaps it's just okay that they only fire progress within fetch? Or perhaps it would be doable to fire them elsewhere (if it would even make sense)? My thinking is if the vast majority of cases support progress events then the nicer API is probably a worthy trade off? Response is actually where things are less clear in general though. |
|
|
|
Okay in that case I think the addition should be moved to a fetchInit rather than being part of requestInit, easy enough to do. That way it keeps it separate from request entirely. |
what does that look like? a third argument to fetch? or like |
|
Yeah the FetchInit dictionary would extend RequestInit |
|
I wonder if this should be a single observer object, making it easier to pass around. This also makes more sense if we want somewhere to put an abort event. Also, this would be a good opportunity to move to a more modern pattern of having the details on the target object, rather than on the event object. interface FetchObserver extends EventTarget {
requestLengthComputable: boolean;
responseLengthComputable: boolean;
requestLoaded: number;
responseLoaded: number;
requestTotal: number;
responseTotal: number;
onrequestprogress: (event: Event) => void;
onresponseprogress: (event: Event) => void;
}We could include |
|
Awsome! const translator = await Translator.create({
sourceLanguage: 'es',
targetLanguage: 'fr',
monitor(m) {
m.addEventListener('downloadprogress', (e) => {
console.log(`Downloaded ${e.loaded * 100}%`);
});
},
});I think @domenic is responsible for it. |
|
@Terreii thanks for raising this. |
39e371e to
6dd23b7
Compare
2d926b2 to
c03933d
Compare
| interface FetchMonitor : EventTarget { | ||
| attribute EventHandler onrequestprogress; | ||
| attribute EventHandler onresponseprogress; | ||
| }; |
There was a problem hiding this comment.
Perhas we can have requestFinished and responseFinished promises as well?
Still using a ProgressEvent for now, but this will be switched to Event
19b5689 to
cd935ac
Compare
|
Just coming back to this to say it's still on my radar and will try to make progress on this. I think from discussions this overall direction seems okay though? |
This is not ready for review this is WIP.
(See WHATWG Working Mode: Changes for more details.)
Preview | Diff