5

The documentation for jQuery.when() says that this function takes Deferreds. However, it also says later on that:

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise...

which seems to imply that it can take Promises as well. But Promises are not Deferreds - they have a subset of the Deferred's methods. I guess you could say that a Deferred is a Promise, but a Promise is not a Deferred.

Questions:

  1. Can $.when() take either Promises or Deferreds? This seems to work in my testing.
  2. Is there a bug in the doc? I think it should say that $.when() takes Promises, not just Deferreds.
Jonathan Aquino
  • 3,780
  • 1
  • 18
  • 19
  • 1. Yes it can. 2. It might be better suited to ask jQuery developers. – Karl-André Gagnon Apr 05 '16 at 18:53
  • @Karl-AndréGagnon 2. Good idea - I have filed this jquery documentation bug: https://github.com/jquery/api.jquery.com/issues/906 – Jonathan Aquino Apr 05 '16 at 18:59
  • @JonathanAquino `$.when()` can accept `jQuery.Deferred()`, `jQuery.promise()` or native `Promise`. See http://blog.jquery.com/2016/01/14/jquery-3-0-beta-released/ . The documentation at `$.when()` is attempting to describe that `$.when()` can accept a parameter that is nether a `jQuery.Deferred()`, `jQuery` promise object or native `Promise`, and the `.then()` or `.done()` callbacks will treat the passed parameter as a resolve `jQuery.Deferred()` – guest271314 Apr 05 '16 at 19:07
  • @JonathanAquino There are perhaps several features of jQuery methods that are not detailed or even mentioned at documentations. There are also functions available to `jQuery` object not listed at documentations. One approach would be to review the source of jQuery https://github.com/jquery/jquery to compare with descriptions at documentation. You can also try to ask questions at IRC/Chat http://irc.jquery.org/ and forums http://forum.jquery.com/ – guest271314 Apr 05 '16 at 19:24
  • @guest271314: Until 3.0 is really released, you can assume [tag:jquery]-tagged questions not to use it (and the jQuery docs not to cover it). And even then, we might need a new tag, given that they behave vastly different. – Bergi Apr 05 '16 at 19:55
  • @Bergi Yes, the documentations are certainly not exhaustive nor do they include all options for possible parameters of a method or function; nor all available jQuery methods or functions available. For example, `.html()`. Though at present Question, at least from perspective here, OP appears to have omitted second portion of sentence from original Question where description is provided that attempts to explain that any value passed to `$.when()` as a parameter is treated as a resolved `jQuery.Deferred()`. This is available at `$.when()` at jQuery versions before 3.0 – guest271314 Apr 05 '16 at 20:01
  • @Bergi _"Until 3.0 is really released, you can assume jquery-tagged questions not to use it (and the jQuery docs not to cover it). And even then, we might need a new tag, given that they behave vastly different."_ Add `jquery-latest` tag ? Include `"https://code.jquery.com/jquery-git.js"` at stacksnippets ? – guest271314 Apr 05 '16 at 20:59
  • @Bergi http://meta.stackoverflow.com/questions/320491/add-jquery-lastest-tag-include-jquery-lastest-version-at-stacksnippets – guest271314 Apr 05 '16 at 21:12

2 Answers2

3

What the documentation is attempting to convey is that $.when() will accept a value that is neither a jQuery.Deferred(), a jQuery.promise() nor a Promise; the value will be treated as a resolved jQuery.Deferred(), which is described at next portion of sentence

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.

For example

$.when(1).then(function(data) {
  alert(data)
})
<script src="https://code.jquery.com/jquery-git.js">
</script>
guest271314
  • 1
  • 15
  • 104
  • 177
  • I'm asking if $.when can accept promise-like objects. The doc says it only accepts Deferreds. But in my testing, it accepts promise-like objects (i.e., Deferred.promise()). – Jonathan Aquino Apr 07 '16 at 01:39
  • @JonathanAquino _"The doc says it only accepts Deferreds."_ Where does the documentation state this? `$.when()` accepts any variable or object as parameter; not only `jQuery.Deferred()`. What do you mean by "promise-like objects"? What are you trying to achieve using `$.when()`? – guest271314 Apr 07 '16 at 02:18
  • @JonathanAquino _"If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately."_ [`jQuery.when()` documentation](https://api.jquery.com/jquery.when/) – guest271314 Apr 07 '16 at 02:28
  • It states that it only accepts Deferreds at the top of https://api.jquery.com/jquery.when/ - jQuery.when( deferreds ) – Jonathan Aquino Apr 09 '16 at 16:38
  • My point is that when() treats Deferreds and Promises differently from other objects. The top of the doc should say jQuery.when( promises ), not jQuery.when( deferreds ), because promises are more general than deferreds. – Jonathan Aquino Apr 09 '16 at 16:42
  • @JonathanAquino _"It states that it only accepts Deferreds at the top of api.jquery.com/jquery.when"_ The word "only" does not appear at https://api.jquery.com/jquery.when/? – guest271314 Apr 09 '16 at 16:42
  • OK, point taken. But my point still stands: it should say jQuery.when( promises ), not jQuery.when( deferreds ). – Jonathan Aquino Apr 09 '16 at 16:43
  • Because if you are looking for a way to combine several promises into one, then $.when is what you are looking for. – Jonathan Aquino Apr 09 '16 at 16:44
  • @JonathanAquino _"My point is that when() treats Deferreds and Promises differently from other objects."_ In which manner? `$.when()` converts the parameter to a resolved jQuery promise object if the parameter is not a promise or deferred object. _"But my point still stands: it should say jQuery.when( promises ), not jQuery.when( deferreds )."_ ? Not following, here. What do you mean? You should be able to use `$.when()` with multiple deferred objects as a paramter. – guest271314 Apr 09 '16 at 16:46
  • Deferreds implement the promise interface. $.when can handle both promises and deferreds. So it should just say $.when(promises) because it can handle both. – Jonathan Aquino Apr 09 '16 at 16:47
  • I'm talking about jquery promises here (jQuery 2), not real Promise/A promises. – Jonathan Aquino Apr 09 '16 at 16:48
  • @JonathanAquino _"Deferreds implement the promise interface."_ , _"So it should just say $.when(promises) because it can handle both."_ , _"I'm talking about jquery promises here (jQuery 2), not real Promise/A promises."_ Not certain what you are trying to convey? Can you create a jsfiddle http://jsfiddle.net to demonstrate the differences between `jQuery.Deferred()` and `jQuery.fn.promise()` ? And how the expected result, or actual result, is different than described at documentation? – guest271314 Apr 09 '16 at 16:50
  • Alas, I give up :( – Jonathan Aquino Apr 09 '16 at 16:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108712/discussion-between-guest271314-and-jonathan-aquino). – guest271314 Apr 09 '16 at 16:54
3

I guess you could say that a Deferred is a Promise, but a Promise is not a Deferred.

Actually they're completely different interfaces, only jQuery mixed in the promise API into their deferreds. See What are the differences between Deferred, Promise and Future in JavaScript?

Can $.when() take either Promises or Deferreds?

Yes, it can take both. But notice that when you already know to have a promise or a deferred, there is no point in calling $.when on it.

Is there a bug in the doc?

Yes, apparently. And it's not even the truth that it only treats deferreds and promises as asynchronous values - rather it does some kind of duck-typing check. You'll want to have a peek at the actual implementation:

if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) )

It then calls the promise method (or another promise method, or really any .promise method) on the value and expects the returned object to have the respective chainable methods to add listeners.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • That portion of documentation appears to actually be describing `$.when()` accepting any parameter - not only `jQuery.Deferred()` jQuery `.promise()` object or native `Promise` ; and treating that parameter as a resolved `jQuery.Deferred()`. OP omitted remainder of sentence at quote at original Question; thus possible confusion as to documentation quote and what it is attempting to convey - and current Question. OP may be trying to ask what is difference between `jQuery.Deferred()` and jQuery `.promise()` object - and possibly `Promise`; though this is not clear at Question. – guest271314 Apr 05 '16 at 20:05
  • @guest271314: Sure, it think it's clear to everyone that any values not identified as "promiseable" will be treated directly as fulfillment values. My answer only clarifies what is "promiseable" and what is not. – Bergi Apr 05 '16 at 20:59
  • Could you expand on _"But notice that when you already know to have a promise or a deferred, there is no point in calling `$.when` on it."_? I'm still fuzzy on Promise and Deferred and I think a little explanation why (there is no point) would help both me and future visitors. – Stephen P Apr 05 '16 at 22:41
  • 1
    @StephenP: I mean that instead of doing `$.when($.ajax(…)).then(…)` (like in the horrible example in the docs) you should just do `$.ajax(…).then(…)`. `$.when` is only good when you have values supplied by the user (caller of your function) and don't know whether they are a promise or a plain value: `$.when(couldBeAnything).then(function(nowSurelyIsPlainValue) {…})` – Bergi Apr 05 '16 at 22:56
  • @Bergi You said "But notice that when you already know to have a promise or a deferred, there is no point in calling $.when on it." I thought $.when will combine several promises together - isn't that a good reason to use it? – Jonathan Aquino Apr 07 '16 at 01:39
  • @JonathanAquino: Yes, that is a good reason to use it - the problem with `jQuery.when` is that it's a horrible mix between `Promise.resolve` and `Promise.all` – Bergi Apr 07 '16 at 07:51