$.when should always be synchronous when possible #3100

Closed
marcandre opened this Issue May 3, 2016 · 5 comments

Projects

None yet

4 participants

@marcandre

IIC, jQuery 3.0 will have then be A+ compatible in that callbacks are always executed out of context (e.g with setTimeout), while done will continue to be executed synchronously whenever possible (eager).

I was double checking that $.when kept the eager behavior and discovered that it does, unless there's a single argument:

p = $.Deferred()
p.resolveWith(42);
p.done(function() {console.log('A')});
$.when(p).done(function() {console.log('B')});
$.when(p, p).done(function() {console.log('C')});
console.log('D');

I was hope to get ABCD, given that the promised is already resolved when the done are called, and dreaded ADBC if $when was no longer eager. I get worse though. Console is ACDB, which is not acceptable; $.when(p) and $.when(p, p) should behave the exact same way.

FWIW, I personally disagree with Promise/A+'s rule 2.2.4 and I hope jQuery keeps all behavior eager (except for then to comply with A+) and gives us an eager version of then (could be pipe, but with the correct semantics for callbacks return values).

I did not investigate any further, but it looks related to #3059.

@markelog
Member
markelog commented May 3, 2016 edited

@gibson042 Did we discuss this before? Did we want to make done async or sync? I agree arguments shouldn't affect on it

@markelog markelog added the Deferred label May 3, 2016
@gibson042
Member

It's important to realize that jQuery.when is polymorphic—multi-argument calls being analogous to ES6 Promise.all and other calls being analogous to ES6 Promise.resolve. It's unfortunate that their similarity led to a shared function name in jQuery, but they are distinct. And although done itself remains eager, general-case jQuery.when( value ) is necessarily not because of its reliance on .then to unwrap secondary thenables as Promise.resolve does. And I don't want to introduce a jQuery.when( nonThenable ) exception, which really would introduce an inconsistency.

I also disagree with Promises/A+ 2.2.4, but that is insufficient justification to abandon compatibility which has been demanded for so long.

@gibson042 gibson042 closed this May 3, 2016
@dmethvin
Member
dmethvin commented May 3, 2016 edited

I know @gibson042 has rightly railed about this several times, I'm too lazy to dig it up.

In the pre-3.0 implementation there was a special case of "If there is only one argument, and it is a Deferred rather than a plain value, return that argument." In 3.0 we are accepting any type of thenables as arguments, so it would make the $.when behavior even more bizarre because if you passed in a thenable we'd need to convert it to a Deferred to meet the API contract, right? That means there always has to be a hidden async theninside $.when for this to not be a tear-your-hair-out behavior.

Edit: What @gibson042 said.

@markelog
Member
markelog commented May 3, 2016

So, jQuery.when is always async right?

@markelog
Member
markelog commented May 3, 2016

So, jQuery.when is always async right?

I answer myself here - no it is not.

Discuss this with @gibson042 on irc, it seems there is motivation to make this call always async regardless of the arguments, opened a different issue for that - #3102

@markelog markelog assigned markelog and unassigned markelog May 3, 2016
@gibson042 gibson042 added a commit to gibson042/jquery that referenced this issue May 5, 2016
@gibson042 gibson042 Deferred: Make jQuery.when synchronous when possible
Fixes gh-3100
bdb2af5
@gibson042 gibson042 added a commit to gibson042/jquery that referenced this issue May 5, 2016
@gibson042 gibson042 Deferred: Make jQuery.when synchronous when possible
Closes gh-3102
Fixes gh-3100
def8db2
@gibson042 gibson042 added a commit to gibson042/jquery that referenced this issue May 9, 2016
@gibson042 gibson042 Deferred: Make jQuery.when synchronous when possible
Closes gh-3102
Fixes gh-3100
Closes gh-3105
de71e97
@gibson042 gibson042 added this to the 3.0.0 milestone May 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment