0

Am using $.Deferred() to wait for asynchronous call and then get data from it. Tried this so far : http://jsfiddle.net/RMSbx/1/

var result = "";
function asyncCallWrapper () {
  return $.Deferred(function(def) { asyncCallFunction(arg1, function ( //Fires a callback when completed
    def.resolve(data);
  )))
}
$.when(asyncCallWrapper ()).done(function (dataFromAsyncCall) {
  alert(dataFromAsyncCall); // Alerts proper data
  result = dataFromAsyncCall;
});

alert(result);// Empty string

How can I access result outside done()

GoodSp33d
  • 6,252
  • 4
  • 35
  • 67

2 Answers2

1

You can't escape from asynchrony.

$.Deferred cannot wait for an operation; instead, it can run callbacks when the operation finishes.
You must put the code that uses the value in a then() callback.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Am returning the value to some other function, so would that work ? What would the correct syntax for that be ? `$.when(fun()).done().then()` ? – GoodSp33d Jun 03 '13 at 17:34
  • You can return another promise object, but you CANNOT return a value. the value won't exist when you attempt to return it. There is no way around that while keeping it asynchronous. – Kevin B Jun 03 '13 at 17:37
  • @2-Stroker: No; just return the promise. `return fun()` or `return fun.then(function (r) { ... })`. – SLaks Jun 03 '13 at 17:38
1

Your asyncCallWrapper function should return a promise instead of a deferred. Deferreds are meant to be used internally to control when/how the code completes.

function asyncCallWrapper () {
  return $.Deferred(function(def) { asyncCallFunction(arg1, function ( //Fires a callback when completed
    def.resolve(data);
  ))).promise();//return the deferred's promise instead of the deferred itself.
}

$.when is a utility function intended for wrapping multiple promises in a deferred.

$.when(asyncCallWrapper(), asyncCallWrapper(), asyncCallWrapper())
  .done(function(dataFromAsyncCall1, dataFromAsyncCall2, dataFromAsyncCall3) {
    console.log("<ALL> three async calls are successful");
  });

Therefore, it isn't needed and you can just write

asyncCallWrapper()
  .done(function(dataFromAsyncCall) {
    alert(dataFromAsyncCall);
    result = dataFromAsyncCall;
  });

The reason alert(result) is an Empty string is because the actual work hasn't happened yet. At that point in the code, you simply told the application what it should do when the asyncCallWrapper finishes. It hasn't finished it's work at this point.

In your case, you want to read the data after it has been set sometime later. This is what deferred are good for.

asyncCallWrapper()
  .done(function(dataFromAsyncCall) {
    alert(dataFromAsyncCall);
    result = dataFromAsyncCall;
  })
  .then(function() {
    alert(result);//should be dataFromAsyncCall
  });

After reading your comments, I saw you wanted to use the result immediately. This isn't possible with deferreds. You will have to refactor the code that needs the value to call then on the promise.

jcbelanger
  • 539
  • 3
  • 15