2

in my Angular web app, I have a module called ApplicationModule. ApplicationModule has get and set functions.

In one of my controllers, I call function like below:

ApplicationModule.get().then(function (response) {
    //do something with response
});

GET() function returns an object called application. With the returned object, I would like to do something with it. so I use then to chain the method but I get an error saying angular.js:13424 TypeError: Cannot read property 'then' of undefined.

Updated what get() is.

ApplicationModule.get = function () {
        if (!localStorage.application) {
            Restangular.all('session').one('user').get().then(function (response) {
                      application = {
                                    "id": response.current_application_id,
                                    "user_id": response.id,
                                    "visa_type": response.current_type
                                    }
                localStorage.setItem("application", JSON.stringify(application));
                return application
            });
        } else {
            return JSON.parse(localStorage.application)
        }
}

What am I doing wrong here?

peteb
  • 18,552
  • 9
  • 50
  • 62
JoHksi
  • 517
  • 1
  • 7
  • 26
  • `.then()` is usually only used for promise syntax. Your `.get()` method doesn't return a promise, it returns an object. Just do `var response = ApplicationModule.get();` – Andy Ray Jun 14 '16 at 19:33
  • 2
    Well apparently `.get()` does *not* return an object. You'll have to show us its code though if you want us to help you fix the problem. – Bergi Jun 14 '16 at 19:33
  • It sounds like ApplicationModule.get does not exists (is undefined). Are you sure its not GET()? Also it needs to be returning a promise. – terpinmd Jun 14 '16 at 19:34
  • you aren't showing what `get()` returns, only describing that it is supposed to be returning an `application` object. To troubleshoot the problem, it would be necessary to see the full signature of the `get()` method. – Claies Jun 14 '16 at 19:34
  • I just need to call certain function after ApplicationModule.get() is fully run. `ApplicationModule.get()` and other function should be sequential in order not to cause a problem in my app. And `get()` just returns an object which is a JSON. – JoHksi Jun 14 '16 at 19:35

2 Answers2

3

Your method does neither return the application nor does it return an object at all if localStorage.application is falsy.

You are doing something asynchronous in your function, so you need to always return a promise:

ApplicationModule.get = function () {
    if (!localStorage.application) {
        return Rectangular.all('session').one('user').get().then(function (response) {
//      ^^^^^^ returning the promise
            var application = {
                "id": response.current_application_id,
                "user_id": response.id,
                "visa_type": response.current_type
            };
            localStorage.setItem("application", JSON.stringify(application));
            return application;
//          ^^^^^^ returning the value that the promise will resolve with
        });
    } else {
        return $q.resolve(JSON.parse(localStorage.application));
//             ^^^^^^^^^^ creating a promise here as well for consistent interface
    }
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • what does `return Restangular` does? and what does `$q.resolve` do? Never encountered this so I would appreciate your further explanation. – JoHksi Jun 14 '16 at 19:50
  • @JoHksi `Restangular` is just a typo on Bergi's part, you should follow the link he provided in "neither return the application". [`$q.resolve`](https://docs.angularjs.org/api/ng/service/$q#resolve) just signals to the calling function that the promise returned by `ApplicationModule.get()` finished successfully. – peteb Jun 14 '16 at 19:52
  • @peteb, are you suggesting to delete return in front of Restangular then? And how do I write additional function to catch errors? on `ApplicationModule.get()`? – JoHksi Jun 14 '16 at 19:57
  • @JoHksi no I'm not, that is exactly what has been causing your problem, the lack of you returning the promise created by `Rectangular.all()`. Read the comments in the snippet provided by Bergi... – peteb Jun 14 '16 at 19:58
  • @JoHksi: No, we're not suggesting to omit the `return` - the whole point of my answer is that you forgot it in your original code! It does return the promise that the `.then(…)` call returns. – Bergi Jun 14 '16 at 19:59
  • @Bergi, gotcha! on the `ApplicationModule.get()` itself, after calling `then`, how can I catch the error? – JoHksi Jun 14 '16 at 20:00
  • @JoHksi by using a `.catch()` function in your promise chain after your `.then()` – peteb Jun 14 '16 at 20:01
  • @JoHksi: Just chain a `.catch(function(err) { … })` to it, like for any promise. – Bergi Jun 14 '16 at 20:01
  • thank you so much all :) It would be great to see if you guys have any link for more explaining about promise. Not very familiar with this concept :) – JoHksi Jun 14 '16 at 20:02
  • @peteb, i all of sudden started getting an errror saying `ReferenceError: $q is not defined` not sure why :/ – JoHksi Jun 14 '16 at 20:05
  • @JoHksi You need to add it as a dependency to inject into your `ApplicationModule`, `angular.module('ApplicationModule', ['$q', function($q) {}]);` – peteb Jun 14 '16 at 20:05
  • @JoHksi: I've used the [`$q` module](https://docs.angularjs.org/api/ng/service/%24q) implicitly, given your question is tagged [tag:angular-promise] I thought you were already using it. – Bergi Jun 14 '16 at 20:06
  • Thank you all! Really appreciate both of you . – JoHksi Jun 14 '16 at 20:07
  • @Bergi, I have one more question. Is there a way to return `JSON.parse(localStorage.application)` without putting it in $q.resolve()? ApplicationModule.get() is made to return application object, but if `JSON.parse(localStorage.application)` is embedded in`$q.resolve()`, it returns promise object and makes me hard to utilize it. – JoHksi Jun 14 '16 at 23:12
  • @JoHksi: No, that is not possible. In fact, `get()` being made to always return a promise for the application object makes it much easier to utilise than if it sometimes did return the object directly and sometimes did return a promise for it (when it needs to fetch if from Rectangular). If you always return a promise, you are guaranteed to always get your result asynchronusly, and this consistency simplifies async programming a huge lot. – Bergi Jun 14 '16 at 23:27
0

The method .then() is only applicable to promises. In order to do something with your application object I suggest storing the value as a variable.

var application = ApplicationModule.get();
foo(application);
Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143
Isahiro
  • 165
  • 1
  • 2
  • 11