-
Notifications
You must be signed in to change notification settings - Fork 20.5k
Deferred: invoke processes in async groups instead of individually #3228
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,9 @@ function adoptValue( value, resolve, reject ) { | |
| } | ||
| } | ||
|
|
||
| var processQueue = []; | ||
| var processQueueTimeout; | ||
|
|
||
| jQuery.extend( { | ||
|
|
||
| Deferred: function( func ) { | ||
|
|
@@ -183,8 +186,13 @@ jQuery.extend( { | |
| }, | ||
|
|
||
| // Only normal processors (resolve) catch and reject exceptions | ||
| // Exceptions in other cases should not effect the promise result | ||
| process = special ? | ||
| mightThrow : | ||
| function() { | ||
| try { | ||
| mightThrow(); | ||
| } catch ( e ) {} | ||
| } : | ||
| function() { | ||
| try { | ||
| mightThrow(); | ||
|
|
@@ -212,20 +220,26 @@ jQuery.extend( { | |
| } | ||
| }; | ||
|
|
||
| processQueue.push( process ); | ||
|
|
||
| // Support: Promises/A+ section 2.3.3.3.1 | ||
| // https://promisesaplus.com/#point-57 | ||
| // Re-resolve promises immediately to dodge false rejection from | ||
| // subsequent errors | ||
| if ( depth ) { | ||
| process(); | ||
| deferredTick(); | ||
|
Contributor
Author
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. I think this specific line could actually change the execution order of Previously this single Can anyone think of a case where this is wrong?
Member
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. So the only possible callback that might throw and not be caught is the last one, right? However, would something like
Contributor
Author
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.
I'm not sure actually. Can you think of any examples where a throwing function would be pushed onto
All the scenarios I've tried seem to be valid to. Some examples... (where fn1 always executes before fn2, fn3 before fn4 etc). deferred.then(fn1).done(fn2)var def = $.Deferred();
def.then(fn1).done(fn2);
def.resolve(-1);
$.when(5).then(fn3);var def = $.Deferred();
def.then(fn2).done(fn3);
$.when(5).then(fn1);
def.resolve(-1);var def = $.Deferred();
def.then(fn2).done(fn3);
def.resolve(-1);
$.when(5).done(fn1);
Member
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. Sorry, I think the case I was looking for was
Contributor
Author
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. The notify case is an issue, see 4bc074b
Member
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. This PR does introduce some sequence jumping. Note how callbacks follow an orderly progression with the current codebase, but the I'm against this PR as-is, but in favor of the broader refactoring that was hoped for when the Deferred changes first landed, to abstract out Promises/A+ compatibility code for both
Contributor
Author
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. Would it make sense to revert this one line?
Member
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. No, because then things would probably fall out of spec. I'm instead advocating for broader changes that would eliminate the need for doing something different when |
||
| } else { | ||
|
|
||
| // Call an optional hook to record the stack, in case of exception | ||
| // since it's otherwise lost when execution goes async | ||
| if ( jQuery.Deferred.getStackHook ) { | ||
| process.stackTrace = jQuery.Deferred.getStackHook(); | ||
| } | ||
| window.setTimeout( process ); | ||
|
|
||
| // Ensure processing has been scheduled | ||
| if ( !processQueueTimeout ) { | ||
| processQueueTimeout = window.setTimeout( deferredTick ); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
@@ -385,5 +399,12 @@ jQuery.extend( { | |
| } | ||
| } ); | ||
|
|
||
| function deferredTick() { | ||
| processQueueTimeout = undefined; | ||
| jQuery.each( processQueue.splice( 0, processQueue.length ), function( _, process ) { | ||
| process(); | ||
| } ); | ||
| } | ||
|
|
||
| return jQuery; | ||
| } ); | ||
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.
Swallowing errors from progress callbacks is a problem. We just went through a big exercise with
readyto prevent its analogous situation.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.
This was mainly just to test this out. I'm thinking that exceptions from a progress callback should be handled the same as exceptions in a success/error callback (~20 lines down). If we're ok with that then I think these two methods wrapping
mightThrowcan be combined and thespecialcheck will go within that single wrapper. Basicallyspecialjust means thatmightThrowthrowing does not reject the promise...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.
So send them through
exceptionHook? Yeah, that makes sense.