2

Consider the following:

function foo(){
  // Returns the jQuery deffered below.
    var urlToUse;
     $.ajax({
          url:'someUrl',
          success:function(res){urlToUse= res;}
     }).then(function(){
       return  $.ajax({url:urlToUse,
             success:function(){
                //Do something 
             }
         }); // I want to return this deffered object!
     })
}

Is there a way to return the promise within the promise?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Skarlinski
  • 2,419
  • 11
  • 28

2 Answers2

3

You just did. There are 3 things that can happen in a jQuery then:

If you don't return anything at all to then, the next chained then will resolve with the same value as the previously attached then.

$.ajax(...)
  .then(function(result){ // result = 5
    // This block executes when the first AJAX resolves
    // Do nothing
  })
  .then(function(result){ // result = 5
    // This block executes right after the previous `then`
    // and still uses the same resolved value
  });

If you return a promise (like from a jQuery ajax or Deferred), the next chained then will resolve when that returned promise resolves.

$.ajax(...)
  .then(function(firstAjaxResult){
    // This block executes when the first AJAX resolves

    // Return a promise
    return $.ajax(...);
  })
  .then(function(secondAjaxResult){
    // This will resolve when the second AJAX resolves
  });

If you return anything other than a promise, the next chained then will resolve with the value returned by the previous then instead of the original value.

$.ajax(...)
  .then(function(result){ // result = 5
    // This block executes when the first AJAX resolves

    // Return a modified result
    return result * 3;
  })
  .then(function(newResult){ // newResult = 15
    // This block executes right after the previous `then`
    // but resolves with the modified value
  });
Joseph
  • 117,725
  • 30
  • 181
  • 234
  • Wouldn't the function return undefined, since deffered is still not resolved? – Skarlinski Apr 12 '15 at 15:51
  • @Skarlinski the `.then()` function returns a separate Promise from the one that your callback returns. That Promise *waits for your promise to resolve*, thus effectively doing exactly what you want. – Pointy Apr 12 '15 at 15:53
  • @Skarlinski `$.ajax(...).then(fun1).then(fun2)` will mean that `fun2` will be run when the promise returned by `fun1()` is fulfilled. – Pointy Apr 12 '15 at 15:59
  • Note that this behavior breaks in 3.0 which spec-conforms to promises. – Benjamin Gruenbaum Apr 12 '15 at 20:08
2

You just need to return the promise returned by the outer $.ajax chain. Replace $.ajax... with return $.ajax...

You can actually write this much more concisely, since .then is a replacement for using success: callbacks

function foo(){
     // | This return is all you need to add to make your current code work      
     // V
     return $.ajax({url:'someUrl'}).then(function(res) {
         var urlToUse = res;
         return $.ajax({url: urlToUse});
     }).then(function(secondRes) {
         //Do something
         return "Got: " + secondRes;
     });
}

Which you can then use as:

foo().then(function(finalRes) {

}, function(someError) {

});
Eric
  • 95,302
  • 53
  • 242
  • 374