GoodSp33d
GoodSp33d

Reputation: 6282

jQuery Deferred usage

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()

Upvotes: 0

Views: 99

Answers (2)

jcbelanger
jcbelanger

Reputation: 549

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.

Upvotes: 1

SLaks
SLaks

Reputation: 887305

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.

Upvotes: 1

Related Questions