7

I'm still trying to wrap my head around using JQuery's Deferred objects, and am scratching my head at one particular problem. In the following code, I initially tried to chain deferred.then() but it never worked. All three functions execute at once. Only after my co-worker pointed me to the pipe function did things fall into place. Question is, why does pipe() work, but not then()?

var otherDefer = function(msg){return function(){return testDefer(msg)}}; var there = otherDefer("there,"); var guy = otherDefer("guy."); function testDefer(msg) { var deferred = $.Deferred(); pretendAjaxCall( function() { $('<li>'+msg+'</li>').appendTo('#msgOut'); deferred.resolve(); }); return deferred.promise(); } function pretendAjaxCall(callback) { setTimeout(callback,1500); } $.when(testDefer("Hi")).pipe(there).then(guy);​ 

I also tried return deferred instead of return deferred.promise() when using when().then().then().

jsFiddle for above code: http://jsfiddle.net/eterpstra/yGu2d/

3
  • The fiddle works fine for me using "then().then()" (Chrome). Commented Sep 4, 2012 at 23:35
  • the way I understand it, .then returns the original deferred object, allowing for other then, done, fail, etc calls on it. .pipe filters the result and can return a new deferred/promise and any subsequent thens, dones, fails in the chain will act on that object rather than the original. Commented Sep 4, 2012 at 23:57
  • this above answer is for Jquery 1.8 and below, read below answers Commented May 25, 2017 at 19:31

3 Answers 3

6

Since jQuery 1.8 then() returns a new Promise (the same as pipe()) instead of the same Deferred that when() returns.

Change the jQuery version to 1.8.3 or above in your example at:

http://jsfiddle.net/eterpstra/yGu2d

and

$.when(testDefer("Hi")).then(there).then(guy);

will work.

Sign up to request clarification or add additional context in comments.

1 Comment

At the time this question was asked, jQuery 1.8 was still quite new which is probably why none of the older answers suggest updating. Still, good to have an update for future users facing this problem so they don't start using deprecated functions in new code.
5

This is how then() and pipe() work in your sample:

then() returns Deferred and by calling then() on this same Deferred you simply add a second callback to it which will be called simultaneously with the first one

pipe(), instead, returns new Promise allowing you to build a chain and that's why you get sequential calls in this case


Take a look at the following resources for more info about pipe/then:

When should I use jQuery deferred's "then" method and when should I use the "pipe" method?

Promise Pipelines in JavaScript

1 Comment

The 'Promise Pipelines in JavaScript' article was super-useful. Thanks!
2

You're using .then in a way it's not supposed to be used--you're arguing a Deferred to it, when all that .then expects is a plain function to be added as a callback.

The .then method returns the original Deferred, which has been resolved already. When the Deferred resolves, all callbacks added with .then are executed immediately.

On the other hand, the .pipe function takes either a set of functions, or a Promise (which is what you're sending it) and resolves based on the status of the original Deferred. The functionality of .pipe is actually what you're looking for!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.