16

I am writing a parser littered with Async Tasks. I use JQuery promises to control and order the async tasks. This is a psuedo code version of the constructor function:

   /**
     * @constructor
     */
    function Parser(json)
    {   
        return $.when(
            this.delete().then(this.insert(json)),
            this.doSomething(),
            this.doSomethingElse().then(this.update(json))
        ) 
    };

and this is what an example function looks like:

Parser.prototype.doSomething = function()
{   
    var dfd = $.Deferred();

    exampleTask(dfd.reject, dfd.resolve);

    return dfd.promise();
};

From the JQuery docs:

In the case where multiple Deferred objects are passed to jQuery.when, the method returns the Promise from a new "master" Deferred object that tracks the aggregate state of all the Deferreds it has been passed

How can I use .progress() to notify anybody that cares about the overall progress of the Parser? e.g.

var parser = new Parser(json);
parser.progress(function(prog){console.log(prog});

Heres a fiddle with what I'm trying to do: http://jsfiddle.net/ashanova/RjULA/2/

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Jon Wells
  • 4,191
  • 9
  • 40
  • 69

1 Answers1

17

Use deferred.notify() to call the progressCallbacks. For example:

function doSomething() {   
    var dfd = $.Deferred();

    var count = 0;
    var intervalId = setInterval(function() {
        dfd.notify(count++);
        count > 3 && clearInterval(intervalId);
    }, 500);

    return dfd.promise();
};

var promise = doSomething();

promise.progress(function(prog) {
  console.log(prog);
});​

DEMO.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
João Silva
  • 89,303
  • 29
  • 152
  • 158
  • I figured out how to use .notify within a function (as in your demo), but I want to pass it back up to the constructor and notify the overall progress from there. I want to see where the parser is up to overall, not its functions - if you follow me? – Jon Wells Aug 22 '12 at 14:56
  • @CrimsonChin: Not sure if I've understood your question correctly, but in that case, you'd need to create and store a reference to the `$.Deferred` in your constructor, so that you can call `notify` within each method. Something along these lines: http://jsfiddle.net/B7nzy/ – João Silva Aug 22 '12 at 15:16
  • thats a lot closer! I thought that if the $.when created a "master" deferred than perhaps I could notify progress directly to that – Jon Wells Aug 22 '12 at 15:23
  • 1
    @CrimsonChin: `$.when` doesn't create a `$.Deferred` but a `Progress`, that's why you can call `notify` on it. Also note that you *can* accomplish the same thing by passing a simple callback function into the constructor: http://jsfiddle.net/Fubq4/. – João Silva Aug 22 '12 at 15:37
  • Good point about the callback, perhaps I am overcomplicating it? Mind you, this is exactly what notify is for. I have ended up doing this: http://jsfiddle.net/ashanova/HMStX/7/. What do you think? - thanks btw – Jon Wells Aug 22 '12 at 16:06
  • Looks good! Although someone less familiar with `$.Deferred` might not understand that there's a *master* deferred for notifying progress, and a regular deferred for each task. – João Silva Aug 22 '12 at 16:15
  • 4
    @JoãoSilva "$.when doesn't create a $.Deferred but a **Promise**, that's why you **can't** call notify on it" FTFY – Fabian Schmengler Feb 07 '13 at 22:27