35

I have a function that does something like this:

function do_something() {
    // some code

    return $.when(foo, bar, baz).then(do_something_else);
}

function do_something_else(_foo, _bar, _baz) {
    // do something else

    return /* the original inputs */;
}

So, when someone uses do_something, they can also chain more callbacks, like:

do_something().then(function(_foo_2, _bar_2, _baz_2) {
    console.log(_foo_2, _bar_2, _baz_2);
});

The problem is that I don't know how to bypass the original return from do_something_else to the anonymous function described. I don't want to receive a list, but positional arguments instead, so "when foo" inserts some value to do_something_else's _foo and then the same value goes to _foo_2.

How can I do it in JS?

Lucas Sampaio
  • 1,568
  • 2
  • 18
  • 36

1 Answers1

69

Use an anonymous function inside of .then and pass the parameters that you want to pass. I'm replacing .then with .done because you don't need .then in this case.

function do_something() {
    // some code

    return $.when(foo, bar, baz).done(function(_foo_2, _bar_2, _baz_2){
        do_something_else.apply(this,_foo_2);
    });
}

.then actually creates a new deferred object and sends that to the chain. Since you didn't return anything from .then, the new deferred object has no arguments. See this example:

$.when($.Deferred().resolve(2), $.Deferred().resolve(4))
.then(function(a,b) { 
    console.log(a,b); // 2,4
    return $.Deferred().resolve(a,b,6);
}).then(function(a,b,c) { 
    console.log(a,b,c); // 2,4,6
});

If you instead just used .done, it would work as expected.

$.when($.Deferred().resolve(2), $.Deferred().resolve(4))
.done(function(a,b) { 
    console.log(a,b);
}).done(function(a,b) { 
    console.log(a,b);
});

The most common use for .then is chaining ajax requests:

$.ajax({...}).then(function(){
    return $.ajax({...});
}).then(function(){
    return $.ajax({...});
}).then(function(){
    return $.ajax({...});
}).then(function(){
    return $.ajax({...});
});

which can also be easily done in a loop. Each .then will have access to the returned data from the previous request.

Rarepuppers
  • 723
  • 1
  • 10
  • 21
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • What's the difference between .done and .then in this case? I'm running [this example](https://gist.github.com/anonymous/5823503) – Lucas Sampaio Jun 20 '13 at 15:02
  • 6
    `.then` will create a new deferred and add that to the chain. The next thing you do on the chain, such as `.done` or `.then`, will only have access to what was returned from the previous `.then`. – Kevin B Jun 20 '13 at 15:08
  • 1
    @KevinB: Is that how jQuery implemented it? Sad :( In the original proposal, the new promise is resolved with the original results if none is returned from the `.then` callback. – Felix Kling Jun 20 '13 at 15:25
  • @FelixKling That's what i thought it was originally too, but further testing shows that isn't the case. I'm kinda confused atm about it. http://jsfiddle.net/75L9a/2/ – Kevin B Jun 20 '13 at 15:27
  • 2
    @FelixKling After further reading, i see where teh confusion is. The functionality you are referring to was added in 1.5 and removed in 1.8 when `.then` over-took `.pipe`'s functionality. .then's arguments are now done and fail *filters* rather than callbacks. – Kevin B Jun 20 '13 at 15:32