locked
WinJS Promise misses one progress function call

    Question

  • I created a WinJS.Promise and inside it, I have two "progress" calls - but only one gets reported. The first progress callback is not called. 

    Below is the code snippet. How do I make both "progress" calls to be reported.

    document.addEventListener("DOMContentLoaded", initialize, false);
    
    function initialize() {
    
        feedGetAsync("http://blogs.msdn.com/b/b8/atom.aspx").then(
                        function (ev) { console.log("success");},
                        function (ev) { console.log("failure"); },
                        function (ev) { console.log("progress"); });
    }
    
    function feedGetAsync(url) {
        
        return new WinJS.Promise(function (completed, failed, progress) {
            try {
    
                var uri = new Windows.Foundation.Uri(url);
                var synd = new Windows.Web.Syndication.SyndicationClient();
                synd.bypassCacheOnRetrieve = true;
                progress();
                synd.retrieveFeedAsync(uri).done(function (f) {
                    progress();
                    completed();
                }, function () {
                    failed();
                });
            }
            catch (ex) {
                failed();
            }
    
        });
    
    }


    • Edited by joemetro Monday, June 18, 2012 8:22 PM
    Monday, June 18, 2012 6:29 PM

Answers

  • No, there is no way to guarantee any progress calls.  retrieveFeedAsync already returns a promise, though it is a WinRT promise and not a WinJS promise.  You should be able to do any promise chaining you need for your computation with that promise alone, without having to wrap the synchronous code prior to retrieveFeedAsync in an additional WinJS promise.

    function initialize() {
        try {
            feedGetPromise("http://blogs.msdn.com/b/b8/atom.aspx-fail", function (ev) { console.log("progress"); }).then(
                function (ev) { console.log("success"); },
                function (ev) { console.log("failure"); },
                function (ev) { console.log("progress"); });
        } catch (ex) {
            console.log("failure");
        }
    }
    
    function feedGetPromise(url, progress) {
            var uri = new Windows.Foundation.Uri(url);
            var synd = new Windows.Web.Syndication.SyndicationClient();
            synd.bypassCacheOnRetrieve = true;
            progress();
            return synd.retrieveFeedAsync(uri);
    }


    Tuesday, June 19, 2012 4:26 PM

All replies

  • Syntax error?  You are missing a semicolon after completed.

       progress();
       completed
    ();

    Jeff Sanders (MSFT)

    Monday, June 18, 2012 7:21 PM
    Moderator
  • I corrected the semicolon syntax error, same result. 

    I verified by copy-pasting above code into a blank project, and checking log messages.

    Monday, June 18, 2012 8:24 PM
  • The promise does not wait for the call to .then to begin execution.  So, in this case, when the first call to progress() is made, the handlers are not hooked up yet.  The promise will store the result of successful completion or error to report to later handlers, but it does not report old progress calls to later handlers as that information would be out of date.  For this reason, progress handlers on promises are not guaranteed to receive all or any (in the case that the promise completes with either success or error before handlers are hooked up) progress notifications.

    Tuesday, June 19, 2012 3:06 AM
  • so is this by design...how do I get a guaranteed "progress". For example, in my code above, I need to report to users that one of several promises is ready to download feed (the first progress call does this).  Then the second progress call will let the users know the feed-download is complete. With this limitation, I could not report "progress" before starting of the download. Only the "progress" after the download gets executed.
    Tuesday, June 19, 2012 5:00 AM
  • It sounds like you don't really want to wrap this in a WinJS promise.  It isn't really gaining you anything in this case.  Maybe you want something more like:

    function initialize() {
    
        feedGetAsync("http://blogs.msdn.com/b/b8/atom.aspx-fail",
                        function (ev) { console.log("success"); },
                        function (ev) { console.log("failure"); },
                        function (ev) { console.log("progress"); });
    }
    
    function feedGetAsync(url, completed, failed, progress) {
        try {
    
            var uri = new Windows.Foundation.Uri(url);
            var synd = new Windows.Web.Syndication.SyndicationClient();
            synd.bypassCacheOnRetrieve = true;
            progress();
            synd.retrieveFeedAsync(uri).done(completed, failed, progress);
        }
        catch (ex) {
            failed();
        }
    }
    


    Tuesday, June 19, 2012 3:17 PM
  • actually, I would be doing some heavy computation (potentially blocks for few milliseconds) once the feed download is completed. (analyzing the feed, searching etc). I also will have several feeds in sequence that I would download, then do some heavy computation on each feed. I think wrapping inside a promise would give my UI enough time to display results of each feed.

    In general, do we assume "progress" calls are not guaranteed ? if needed, can we get some critical progress calls to be guaranteed. thanks for you responses, very helpful.

    Tuesday, June 19, 2012 3:35 PM
  • No, there is no way to guarantee any progress calls.  retrieveFeedAsync already returns a promise, though it is a WinRT promise and not a WinJS promise.  You should be able to do any promise chaining you need for your computation with that promise alone, without having to wrap the synchronous code prior to retrieveFeedAsync in an additional WinJS promise.

    function initialize() {
        try {
            feedGetPromise("http://blogs.msdn.com/b/b8/atom.aspx-fail", function (ev) { console.log("progress"); }).then(
                function (ev) { console.log("success"); },
                function (ev) { console.log("failure"); },
                function (ev) { console.log("progress"); });
        } catch (ex) {
            console.log("failure");
        }
    }
    
    function feedGetPromise(url, progress) {
            var uri = new Windows.Foundation.Uri(url);
            var synd = new Windows.Web.Syndication.SyndicationClient();
            synd.bypassCacheOnRetrieve = true;
            progress();
            return synd.retrieveFeedAsync(uri);
    }


    Tuesday, June 19, 2012 4:26 PM