Why is my deferred object set to resolved instead of pending when calling a function that sets a new $.Deferred multiple times?

StackOverflow https://stackoverflow.com/questions/16892864

Question

I'm trying to get jQuery deferred to work and am having some problems.

My system is using postMessage to pass messages from and to sandboxed areas on a website. So when I request a service from a sandboxed area like this:

// on click of button
foo.requestService(options, function (response) {
    $("#c").val(response); // set value of input button
}

Internally, I'm creating a new $.deferred every time the button is clicked and the service is requested like so:

that.requestService = $.fn.requestService = function (options, callbackFunction) {
    var deferred = new $.Deferred(),
        callbackId = priv.generateUuid(),
        callback = deferred;

    // store callback to be retrieved by response handler
    priv.trackCallback(callbackId, callback, callbackFunction);

    // set type
    if (options.type === undefined) {
        options.type = "request/any";
    }
    // the callback function to be run, once a postMessage
    // with the response is received
    deferred.done(function(result, callbackFunction) {
        if (callbackFunction) {
            callbackFunction(result);
        }
    });
    // trigger messaging
    window.top.postMessage(options, window.location.href);
};

All works well, I can request my sandboxed service, run it, postMessage the result and retrieve the respective callback:

priv.returnResult = function (event) {
    // here I get back the deferred (callback[0]) and callback function (callback[1])
    var callback = priv.retrieveCallback(event.data.callback);

    // problem = the callback stays resolved after the first function call
    console.log(callback[0].state());

    callback[0].resolve(event.data.result, callback[1]);
};

My problem is, although I'm creating a **new** $.Deferred every time a service is requested, my deferred object only runs the first time and then is set to resolved, preventing any further function calls to return a result.

I thought a new $.Deferred would generate a new deferred every time a service is requested, which I can resolve to run my callback function.

Question
What do I need to do to get this to work? Is it not, that new creates a new object, which I can resolve? Do I have to somehow delete/remove the previous resolved.deferred object in order to make it work?

Thanks!

Was it helpful?

Solution

Found a snippet extending jQuery deferred to handle "multiple deferred setters and resolvers":

$.extend({
  StatelessDeferred: function () {
    var doneList = $.Callbacks("memory"),
      promise = {
        done: doneList.add,

        // Get a promise for this deferred
        // If obj is provided, the promise aspect is added to the object
        promise: function (obj) {
          var i,
            keys = ['done', 'promise'];
          if (obj === undefined) {
            obj = promise;
          } else {
            for (i = 0; i < keys.length; i += 1) {
              obj[keys[i]] = promise[keys[i]];
            }
          }
          return obj;
        }
      },
      deferred = promise.promise({});

   deferred.resolveWith = doneList.fireWith;
    deferred.resolve = doneList.fire;

    // All done!
    return deferred;
  }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top