0

in my project I'm not using callbacks instead I'm trying to use $.Deferred to have uniform logic across all application, I have lots places in my code where I do something like the following:

function someMagicHandler(request) {
    var me = this;
    var sandbox = me.getSandbox();

    var options = request.options;
    var deferred = request.deferred;

    var result = [];

    var databaseOperation = sandbox.database.all('records').done(function (records) {
        result.concat(records);
        deferred.notify(records);
    });

    var serverResponse;
    var serverOperation = sandbox.server.requestRecords(options).then(function (response) {
        // First we are trying to save received records to database
        serverResponse = response;
        result.concat(response.Records);
        deferred.notify(response.Records);

        return sandbox.database.put('records', response.Records);
    }).done(function() {
        sandbox.storage.setTimestamp('records', new Date(serverResponse.Timestamp));
    });

    $.when(databaseOperation, serverOperation).then(deferred.resolve, deferred.reject);
}

In this code I'm personally don't like one of the last lines:

$.when(databaseOperation, serverOperation).then(deferred.resolve, deferred.reject);

Is there a standard way to express:

$.when(databaseOperation, serverOperation).then(deferred);

which would essentially mean:

$.when(databaseOperation, serverOperation).then(deferred.resolve, deferred.reject, deferred.notify);

Edit

I've investigated this problem deeper, and it seems that below solution is ok only when you are not relying on deferred.progress() which has no memory and therefore will not return any data in case when subsequent async operation is complete synchronously.

Summary

If you are using $.Deferred() as a callback (i.e. when you rely on notify or progress functions and in that case you need pass it as an argument) than you will be obligated to use the ugly

blahblahblah.then(deferred.resolve, deferred.reject, deferred.notify)
Lu4
  • 14,873
  • 15
  • 79
  • 132
  • Not really, you have to pass the callback to .then if you want it to get called. You could instead use `.done()` `.fail()` and `.progress()`, but i don't think that's any better. – Kevin B Apr 01 '13 at 18:51

1 Answers1

2

You can just replace this

$.when(databaseOperation, serverOperation).then(deferred.resolve, deferred.reject);

with this:

request.deferred = $.when(databaseOperation, serverOperation);

And delete all references to the variable deferred because $.when already creates a promise for you with (as far as I read the manual).

mzedeler
  • 4,177
  • 4
  • 28
  • 41
  • Would you not then run into a problem with the two `.notify()` calls, which are inside `databaseOperation()` and `serverOperation()`? I think it's necessary to do `var deferred = request.deferred = $.Deferred();` (or similar) within `someMagicHandler()` and leave the rest of the code pretty well as it is in the question. – Beetroot-Beetroot Apr 02 '13 at 09:25
  • Well. I overlooked the use of ``notify`` - sorry about that. The documentation doesn't state anything about ``$.when`` taking care of ``notify``/``progress``, so we have to assume it is unsupported. I wrote up a quick test of jQuery 1.8.3 that shows that it is only partially working (read "buggy"): http://jsbin.com/abigop/1/edit – mzedeler Apr 02 '13 at 12:04
  • the documentation for `.when()` may not specifically mention `.notify()` but it is implied, in that `.when()` returns a Promise; and Promises (like Deferreds) are objects which take `.progress()`, `.done()` and `.fail()` callbacks. But that's not really the issue here; even if you didn't know how Deferreds and Promises work, `request.deferred = $.when(databaseOperation, serverOperation);` is only appropriate if `databaseOperation` and `serverOperation` are already defined (as they indeed are), so those function can't include references to `request.deferred`, which is defined later. – Beetroot-Beetroot Apr 02 '13 at 16:35