0

I have a function which will generate the WinJS.xhr promise and return the same to the calling function. But after getting the promise, when doing a .then on it, all I'm getting is an empty array!!!

APPROACH 1:

Here is the function which is returning a promise. It's inside a WinJS.Class.define :

getFeaturedData: function () {
                    var featuredUrl = utils.getRequestUrl(globals.featuredTag, 1, 0);
                    return WinJS.xhr({ url: featuredUrl });

                },

I'm calling that function in home.js and attaching a .then this way:

var promise = MyApp.Services.Movies.getFeaturedData();
promise.then(function(success) {
          var data = success;
      },
      function (error) {
      })

The result variable data is always an empty array which I can't seem to understand why.

APPROACH 2:

If I do .then in the getFeaturedData function itself then it works, surprisingly.

getFeaturedData: function () {
                    var featuredUrl = utils.getRequestUrl(globals.featuredTag, 1, 0);
                    var promise = WinJS.xhr({ url: featuredUrl });
                    promise.then(function (success) {
                        var data = success;
                    })

                },

In this case, data seems to contain proper data returned from the server.

Can anyone explain this behavior? Why the first approach doesn't work and the second one does?

Harsha Bhat
  • 718
  • 10
  • 25
  • No, this behaviour indeed makes no sense. Are you sure that in #1, you really are calling the same `getFeaturedData` function as you defined directly, or is something intercepting the call? Also try to install both `then` handlers (and `return` the `data` from the first), and see what it logs. – Bergi Sep 03 '14 at 15:10

2 Answers2

0

In example 1, getFeaturedData is returning a promise.
In example 2, it returns nothing (i.e. undefined).

However, the timing when "data" is set is unchanged. You're setting the "data" value in the completion handler of the XHR in both cases. Most likely the difference lies in where you had set your breakpoint. In neither case will "data" be set at the end of getFeaturedData, or at the end of the calling block of code. Instead, it will be set sometime later when the XHR promise completes.

A couple other notes:

  1. Approach 2 can return the result of promise.then() (which is another promise) so that the caller can actually schedule work to happen once data is set.
  2. In both cases, the "promise" variable is kind of extraneous, or it could be set to the result of either getFeaturedData().then(), or xhr().then().
Colin Cline
  • 1,291
  • 1
  • 12
  • 25
Brandon Paddock
  • 312
  • 1
  • 6
-2

I don't if it is a typo but your first approach is missing an ')' at the end of the function error to enclose the promise result.

Other than that, I can't see why the 1st approach wouldn't work.

Having said that, here's how I would write it:

getFeaturedData: function () {
    return new WinJS.Promise(function (complete, fail){
        var featuredUrl = utils.getRequestUrl(globals.featuredTag, 1, 0);
        WinJS.xhr({ url: featuredUrl }).then(
        function (data){
            complete(data);
        }, function (err){
            fail(err);
        });
    });
}

MyApp.Services.Movies.getFeaturedData().then(
    function (data){
        //do whatever you want with the data
    }, function (err){
        // handle errors here
    });

It is easier for me to see that getFeaturedData returns a promise. In your case it is clear since it is well known that WinJS.xhr returns a promise, but it will not always be that easy to 'see' right away.

sebagomez
  • 9,501
  • 7
  • 51
  • 89
  • 1
    Wow, a perfect application of the [deferred antipattern](http://stackoverflow.com/q/23803743/1048572)! If you want to document that the code returns a promise, use comments. – Bergi Sep 03 '14 at 15:12
  • That's like suggesting wrapping the return statement of every function that returns a string in `String` and every function that returns a number with `Number` - `function add(x,y){ return Number(x+y);}` is just silly - only this is more risky and more code. – Benjamin Gruenbaum Sep 03 '14 at 15:39
  • Thanks, I guess I fallen in the most common anti-pattern in promises history... I quite don't understand why is it so horrible since I can still chain my promises... but I'll definitely look it up – sebagomez Sep 03 '14 at 15:59
  • Yeah that's a pretty awful way to do it... You don't want to wrap a promise in another unnecessary promise. That's a lot of weird gymnastics for no reason. A better pattern for identifying what returns a promise (which WinRT follows, though not WinJS oddly) is to name your methods with Async at the end. – Brandon Paddock Sep 04 '14 at 21:58
  • FYI: this is where I took it from http://blogs.msdn.com/b/windowsappdev/archive/2013/06/11/all-about-promises-for-windows-store-apps-written-in-javascript.aspx – sebagomez Sep 07 '14 at 00:00