Can I pass Promises to jQuery.when(), or only Defe

2019-02-24 08:56发布

问题:

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.

回答1:

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>



回答2:

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.