-
Notifications
You must be signed in to change notification settings - Fork 20.6k
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
Added support for XHR progress event #1541
Conversation
Ok, I'm sorry... Only latter I realised I should have searched http://bugs.jquery.com/, not this repository. Edited: Well, I've seen other direct pull requests that got merged, so I'll keep this to see if someone reviews my code. But I'll understand if it gets closed. |
It's definitely worth a look from @jaubourg. Before this lands it would need documentation, and that concerns me because it's yet another case where platforms and transports would not work consistently in $.ajax calls. Also, we haven't worked out our standard-Promise story and this complicates it since Promise doesn't support progress yet. |
Yes, I thought about that. I even dedicated some time looking for some kind of existing or proposed "onprogress" event for the script tag, similar to img tag, but no luck (every tag that loads resources should have such an event, imho). I proceeded because:
Regarding this last point, the same is true for xhr requests if As for the Promises, the ongoing long discussion about the progress callback isn't clear about how it should work. Maybe for now that's not something for what Promises are for. Maybe that's something still only for the event listeners/callbacks world. |
This looks pretty tied to working with XHR progress events, but what about a general support for progress callbacks/promises for ajaxTransports in general which the XHR transport could then build off of? |
xhr.js is, of course, tied to the XHR event, but in ajax.js it is somewhat abstracted... The terminology used is the one from the Progress Events specification. Currently other transportations have no mechanism for progress reporting, but that doesn't break the spec, as it states that progress callback is called "zero or more" times. Maybe the callback signature should be progress(progress_ratio) but progress(event), simply passing the ProgressEvent? |
I guess it would depend on how you define what "progress" is. In the case of XHR it's relatively straightforward since we have a spec to state what it means, but in the case of other ajaxTransports that may not be the case. As an example, I have an ajaxTransport where a server may immediately return an HTTP 200, however the real response is generated over the course of a few minutes and is then available at another endpoint. My transport abstracts that away so that you just make a request and the transport completes whenever a response is available at the given endpoint. Progress in that case may not mean what it does for XHR, but maybe it just means "I checked the endpoint for a response, nothing is available yet". Also, I wonder if only a single argument should be passed to the progress handler since that's how real promises behave. I know the existing promises/callbacks all accept multiple args and can't be changed for back-compat reasons, but maybe the bleeding should stop here? |
True, it follows the letter of the docs but not the spirit. Users may intuitively expect that a progress handler will be called if they pass one in. This places a heavier burden on the documentation to disappoint the user in advance so they will not misunderstand. It may also be error prone since the user can do rather minor things (e.g., change the
Custom transports are definitely a rare exception rather than the rule. Since few people know how ajax transports work, it might be better from a maintainability perspective to avoid them so someone could see the full implementation on the app side rather than having the unusual request disappear into
Real |
} | ||
|
||
if (s.progress) { | ||
s.progress.call( callbackContext, progress_ratio, jqXHR); |
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.
Won't this only ever cause the progress function to be called, but have no effect on any functions attached via the progress promise interface?
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.
Yes, it looks like it skips the Deferred progress but calls the callback and fires the (new, yet-to-be-documented) ajaxProgress event.
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 wasn't aware of deferred progress method. But what have we been discussing then?
I will push a commit with "deferred.progress( callbackContext, [ progress_ratio, jqXHR ] );".
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.
About "ajaxProgress" event, is just a global event like the others "ajaxXXXX" events.
Then maybe we should call the handler once, so the user knows the progress is indeterminate (which also can happen on XHR)?
This implementation focus on resource download, that's what the Progress Events spec covers. Bytes transferred, not work done. Even the request's upload time isn't part of the progress. This is similar to one of the main questions in the discussion of
I created the As the |
progress_ratio = loaded / total; | ||
} | ||
|
||
deferred.progress( callbackContext, [ progress_ratio, jqXHR ] ); |
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.
notify
or notifyWith
is actually the method you're looking for here, progress
is used to attach handlers.
You may want to look at https://github.com/jquery/jquery/blob/master/src/ajax.js#L616-L618 and follow suit so that the ordering of callbacks is maintained, otherwise this would be backwards from the order others are fired. that would also allow you to delete the call to s.progress below
Many thanks dcherman, I usually don't use jquery deferred, so made a little mess... And because I was calling the callback directly, nothing was wrong in the tests. Please see if I'm closer to getting this right. ;-) |
No problem, @jaubourg is the master here though, I've just written a bunch of plugins for ajax so I'm familiar with it :) Code-wise it looks fine now to me though.
Sure, but there is almost no difference in code to support a generic progress handler. All you have to do is pass something like
As the progress argument for a transport. The XHR transport could then easily support what this PR does, but other transports could implement their own progress notifications however they see fit. |
I saw in @jaubourg profile that he did some contributions last week, after some time away, so I'm bumping this thread. In my projects I'm currently adding the progress event listener in the settings' Thanks. |
@nantunes don't worry about the long delays, I've tagged this for 1.12/2.2 which we haven't really started on. Right now we're working on the next patch releases. We wouldn't want to land this until we've finished the patch release. As I mentioned above, my main concern would be the additional API and documentation. I don't think we need an @jaubourg your thoughts? |
@dmethvin FWIW A few minutes ago I had someone ask me to enhance the long-polling transport that I mentioned earlier to provide progress notifications, so there is an actual use case for progress notifications outside of XHR if that helps |
I am concerned that the |
"progress" callback can be supplied via options. Also created global event ajaxProgress.