Bug Tracker

Modify

Ticket #11894 (closed bug: invalid)

Opened 11 months ago

Last modified 11 months ago

Deferred.notify does not pass expected messages

Reported by: mankyd@… Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.7.2
Keywords: Cc:
Blocking: Blocked by:

Description

I was writing a preloader for a project I was working on. The project has a set of slides that it needs to load content for. When each slide starts its preloading, it is supposed to notify up the chain that it is starting, then notify again that it is finishing, before finally resolving the deferred. What I have noticed is that while the first two calls to notify work as expected, subsequent calls do not. Instead, they simply repeat the second call over. This is best demonstrated by example.

Expected output of the following code:

slide_loading
slide_loaded
slide_loading
slide_loaded
slide_loading
slide_loaded

Actual output:

slide_loading
slide_loaded
slide_loaded
slide_loaded
slide_loaded
slide_loaded

Code:

function Slide() {
    this.preload = function() {
        var preload_deferred = new $.Deferred();
        setTimeout(function() {
            preload_deferred.notify('slide_loading');
            preload_deferred.notify('slide_loaded');
            preload_deferred.resolve();
        }, 1000);
        return preload_deferred.promise();
    };
}
var slides = [new Slide(), new Slide(), new Slide()];
var d = [];
for (var i = 0; i < slides.length; i++) {
    d.push(slides[i].preload());
}
var w = $.when.apply(null, d);
w.progress(function(msg) { console.log(msg);});

If you replace the last line with:

w.progress(function() { console.log(arguments);});

You actually get something like the following out:

["slide_loading", undefined, undefined]
["slide_loaded", undefined, undefined]
["slide_loaded", "slide_loading", undefined]
["slide_loaded", "slide_loaded", undefined]
["slide_loaded", "slide_loaded", "slide_loading"]
["slide_loaded", "slide_loaded", "slide_loaded"]

Change History

comment:1 Changed 11 months ago by mankyd@…

I realize that a jsFiddle demonstrating all of this would be nice:

 http://jsfiddle.net/3duVe/

comment:2 Changed 11 months ago by jaubourg

  • Status changed from new to closed
  • Resolution set to invalid

That's not how notification works: only the latest progress value is kept "in memory" since the Deferred already progressed to that point.

Once your preload has reached the slide_loaded progress state and it is resolved, then the Deferred will never ever get back to the slide_loading state: it will stay in its current state indefinitely.

To understand why, just mentally replace slide_loading and slide_loaded with "0%" and "100%". Once "100%" is reached, it doesn't make sense to go back to "0%", does it?

How did you expect notify/progress to work?

Last edited 11 months ago by jaubourg (previous) (diff)

comment:3 Changed 11 months ago by anonymous

Hmm. My parent deferred is composed of multiple "child" deferreds that are unaware of each other. I was expecting each child to be able to report there progress individually, and have the parent be able to aggregate that information itself. Thus each child could report that they started the loading process and then, later, report that they finished the loading process.

BUT, I just realized something that makes this a moot point. What is actually being reported to the callback, via the arguments variable, is an array of the statuses. Thus if there is 1 child, one message will be passed back. If there are 20 children, 20 messages will be passed back. This is stated, sort of, in the documentation: "If the master Deferred is resolved, it is passed the resolved values of all the Deferreds that were passed to jQuery.when."

It may be worth making this a little clearer by having the documentation make explicit mention of progress in addition to resolved, or by including an example. Thanks!

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.