locked
Create Promise with progress

    Question

  • I'd like to know how to create a custom promise that has a progress callback, did something like:

    runPromise("3").then(function ()
        {
            console.log("done");
        },
       function (err)
        {
            console.log(err);
        },
       function (percent)
        {
            console.log("progress " + percent);
        });

    function runPromise(url)
    {
        return new WinJS.Promise(function (c, e, p)
        {
            if (url == "1") c();
            if (url == "2") e("err");
            if (url == "3") p(5);
        },
        function ()
        {
           console.log("Canceled");
        });
    }

    But progress callback is never invoked, what did i miss?


    Corrado Cavalli [Microsoft .NET MVP-MCP]
    UGIdotNET - http://www.ugidotnet.org
    Weblog: http://blogs.ugidotnet.org/corrado/
    Twitter: http://twitter.com/corcav
    Sunday, October 9, 2011 4:41 PM

Answers

  • Here you go Corrado!

    I created a default HTML app and added a button and label:

     

     

    <buttonid="btnPush">Push Me</button>

    <label id="lblResult" style="width: 81px;"></label>

     

    then I wired up the click:

     

    if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {

     

     document


    .getElementById('btnPush').addEventListener('click', onBtnClicked, false);

     

    defined a promise that updated progress:

     

    function addAsync(l, r) {
     return new WinJS.Promise(function (complete, error, progress) {
    setTimeout(function () {
     try {
     // The + may throw an exception if l and r are not compatible
     // data types. In that case we catch the exception and route it
     // into the Promise error callback.
     //
    var sum = l + r;
    var i;
     for (i = 1; i < 100; i++) {
     // show some progress
     progress(i);
     }


     complete(sum);
     } catch (e) {
     error(e);
     }
     }, 100);
     });
     }


    and called it providing the callbacks:

     

    function onBtnClicked() {
    var num = 1;
    var num2 = 2;
    var num = num + num2;
    document.getElementById('lblResult').innerText = "Pushed";

     //provide the completed, error and progress callbacks!
    addAsync(3, 4).then(function (result){ document.getElementById('lblResult').innerText = "Complete"; }, function (error){ }, function (progress){ Debug.writeln(progress); })


    }


    Jeff Sanders (MSFT)
    Monday, October 10, 2011 3:07 PM
    Moderator

All replies

  • Here you go Corrado!

    I created a default HTML app and added a button and label:

     

     

    <buttonid="btnPush">Push Me</button>

    <label id="lblResult" style="width: 81px;"></label>

     

    then I wired up the click:

     

    if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {

     

     document


    .getElementById('btnPush').addEventListener('click', onBtnClicked, false);

     

    defined a promise that updated progress:

     

    function addAsync(l, r) {
     return new WinJS.Promise(function (complete, error, progress) {
    setTimeout(function () {
     try {
     // The + may throw an exception if l and r are not compatible
     // data types. In that case we catch the exception and route it
     // into the Promise error callback.
     //
    var sum = l + r;
    var i;
     for (i = 1; i < 100; i++) {
     // show some progress
     progress(i);
     }


     complete(sum);
     } catch (e) {
     error(e);
     }
     }, 100);
     });
     }


    and called it providing the callbacks:

     

    function onBtnClicked() {
    var num = 1;
    var num2 = 2;
    var num = num + num2;
    document.getElementById('lblResult').innerText = "Pushed";

     //provide the completed, error and progress callbacks!
    addAsync(3, 4).then(function (result){ document.getElementById('lblResult').innerText = "Complete"; }, function (error){ }, function (progress){ Debug.writeln(progress); })


    }


    Jeff Sanders (MSFT)
    Monday, October 10, 2011 3:07 PM
    Moderator
  • Hi Jeff,
    Thanks for the answer.
    Is there a reason why progress callback must be invoked after a short delay? back to my short sample:

    return new WinJS.Promise(function (c, e, p)
        {
            if (url == "1") c();
            if (url == "2") e("err");
            if (url == "3")
            {
                p(10);
                var handle= setTimeout(function ()
                {               
                    p(42);
                }, 10);
            }
        },
        function ()
        {
            console.log("Canceled");
        });

     p(10) is not invoked, while p(42) yes. I presume because callbacks aren't "wired" yet but, if so, why only progress one?

     


    Corrado Cavalli [Microsoft .NET MVP-MCP]
    UGIdotNET - http://www.ugidotnet.org
    Weblog: http://blogs.ugidotnet.org/corrado/
    Twitter: http://twitter.com/corcav
    Wednesday, October 12, 2011 4:37 AM
  • I believe because your Promise is not executing async.  Try putting the setTimout() on entry of the outer function like my example:

    return new WinJS.Promise(function (complete, error, progress) {
    setTimeout(function () {
    },100);


    Jeff Sanders (MSFT)
    Wednesday, October 12, 2011 5:34 PM
    Moderator
  • Hi Jeff,

          What situation we should put "setTimeout()"?

          In following sample code, it didn't put "setTimeout()", and this sample is not executing async, why did it still use WinJS.Promise()?

          How to modify this code to be  executing in async?

          CanvasPaint\JavaScript\js\filter.js ,

          (http://code.msdn.microsoft.com/windowsapps/CanvasPaint-878fa5d5/sourcecode?fileId=43606&pathId=1158210444)

           function filter(fn) {
            Artboard.createUndoChange();

            return new WinJS.Promise(function (c) {
                var img = Artboard.getImageData();
                fn(img);
                Artboard.setImageData(img);
                c();
            });
        }

        Thank u very much.

    Monday, October 31, 2011 10:58 AM
  • Hi Gary,

    You should use async programming when you expect an operation to block the UI.  I am not sure why there is a promise in that particular sample.  The getImageData and setImageData calls should execute very quickly and are not async calls.  I will see if I can get more information about this sample and reply back.

    -Jeff


    Jeff Sanders (MSFT)
    Monday, October 31, 2011 12:14 PM
    Moderator
  • HI, Jeff

       Is "SetTimeout" function necessary in every custom promise function?!

    Gary

    Tuesday, November 1, 2011 3:06 AM
  • Hi Gary,

    No, the SetTimeout is just an example of how to get Async behavior.  Many APIs have async behavior already and would work fine inside a promise.  Also callbacks can be used.  Look at the end of this documentation for some more on this: http://msdn.microsoft.com/en-us/library/windows/apps/hh464930(v=vs.85).aspx

    -Jeff


    Jeff Sanders (MSFT)
    Wednesday, November 2, 2011 1:38 PM
    Moderator