1

I'm using jQuery 1.8.3 I have a function that returns a new jQuery.Deferred(). When I chain calls to this function using deferred.then(), based on the documentation, I would expect a given function to be called when the preceding function returns, and to receive the jQuery.Deferred() as input.

In practice a given function is called when the preceding function's jQuery.Deferred() is signaled with deferred.resolve(), and receives the value passed to .resolve().

The actual behavior is what I want, but I'm worried I'm relying on undocumented/unsupported behavior, or that I've actually got a bug creating the illusion of what I want.

For example, given

function async_task(i) {
  console.log("Starting async_task(" + i + ")\n");
  var def = $.Deferred();
  setTimeout(function() {
    console.log("    finished " + i + "\n");
    def.resolve(i + 1);
  }, 1000);
  return def;
}

console.log("starting\n");
var p;
p = async_task(1);
p = p.then(async_task);
p = p.then(async_task);
p.then(function() {
  console.log("done\n");
});

the output is

starting
Starting async_task(1)
    finished 1
Starting async_task(2)
    finished 2
Starting async_task(3)
    finished 3
done

but I would expect

starting
Starting async_task(1)
    finished 1
Starting async_task(2)
Starting async_task([object Object])
done
    finished 2
    finished [object Object]

I can certainly imagine that jQuery is probing what the function passed to .then() returns, and if it's a deferred/promise doing what I want, but I can't find documentation supporting that idea.

Why do my expectations based on the documentation not agree with what I'm observing? Have I overlooked documentation? Is this undocumented behavior I shouldn't rely on? Do I actually have a bug?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Alan De Smet
  • 1,699
  • 1
  • 16
  • 20

1 Answers1

4

Looks like you just misread the docs. Admittedly they could be written better.

The sentence you were missing is

These filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks.

While not explained great by jQuery, this adoption ("unwrapping") of further promises is actually one of the outstanding features of promises.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    I'm pretty certain that an earlier version of [that page](http://api.jquery.com/deferred.then/), or maybe somewhere else in the jQuery site made the point better. Otherwise how did I learn it? The almost throw-away words "... or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks" is indeed not enough to make this very important point. – Roamer-1888 Dec 10 '15 at 13:59