Side navigation
#11894 closed bug (invalid)
Opened June 12, 2012 03:38AM UTC
Closed June 12, 2012 11:01AM UTC
Last modified June 12, 2012 11:56AM UTC
Deferred.notify does not pass expected messages
Reported by: | mankyd@gmail.com | Owned by: | |
---|---|---|---|
Priority: | undecided | Milestone: | None |
Component: | unfiled | Version: | 1.7.2 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
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"]
Attachments (0)
Change History (3)
Changed June 12, 2012 04:38AM UTC by comment:1
Changed June 12, 2012 11:01AM UTC by comment:2
_comment0: | 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_loading 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? → 1339498915415039 |
---|---|
resolution: | → invalid |
status: | new → closed |
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?
Changed June 12, 2012 11:56AM UTC by comment:3
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!
I realize that a jsFiddle demonstrating all of this would be nice:
http://jsfiddle.net/3duVe/