Invoking one service from another service in AngularJS

I'm trying to access a service from another service and use the returned object for some operations. However, I keep encountering a

TypeError: getDefinitions is not a function
error.

Here is the code for my services and controller:

definitions.service.js:

'use strict';

angular.module('gameApp')
  .factory('definitionsService', ['$resource',
    function($resource) {
      var base = '/api/definitions';
      return $resource(base, {}, {
        get: {method: 'GET', url: base}
      });
    }]);

utilities.service.js:

'use strict';

angular.module('gameApp')
  .factory('utilitiesService', ['definitionsService',   function(definitionsService) {

    return {
      description: description,
      detail: detail,
      severity: severity,
    };

    function description(account) {
      var key = angular.isDefined(getDefinitions().ABC[account.code]) ? account.code : '-';
      return getDefinitions().IDV[key].description;
    }

    function detail(account) {
      var key = angular.isDefined(getDefinitions().ABC[account.code]) ? account.code : '-';
      return getDefinitions().IDV[key].detail;
    }

    function severity(account) {
      var key = angular.isDefined(getDefinitions().ABC[account.code]) ? account.code : '-';
      return getDefinitions().IDV[key].severity;
    }

    var getDefinitions = function() {
      definitionsService.get().$promise.then(function(data) {
        return data;
      });
    };
  }]);

controller.js:

'use strict';

angular.module('gameApp')
  .controller('AccountsController', AccountsController);

AccountsController.$inject = ['$routeParams', 'customersService', 'utilitiesService'];

function AccountsController($routeParams, playersService, utilitiesService) {
  var vm = this;
  var playerId = $routeParams.playerId;

  var getAccounts = function() {
    playersService.getAccounts({
      playerId: playerId
    }).$promise.then(function(accounts) {
      for (var i = 0; i < accounts.length; i++) {
        if (angular.isDefined(accounts[i].secCode)) {
          accounts[i].code = accounts[i].secCode;
          accounts[i].severity = utilitiesService.severity(accounts[i]);
          accounts[i].detail = utilitiesService.detail(accounts[i]);
          accounts[i].description = utilitiesService.description(accounts[i]);
        }
      }
      vm.accounts = accounts;
    });
  };

  var init = function() {
    getAccounts();
  };

  init();
}

Answer №1

Your service is currently returning before your variable gets defined, leading to an undefined value. To fix this, simply move your variable definition to the top of the function so that it is declared before being used. However, another issue lies in your getDefinitions function which does not return anything despite being called for a property. One possible solution is to use a callback function that executes once the data is loaded:

angular.module('gameApp')
  .factory('utilitiesService', ['definitionsService',   function(definitionsService) {
    var data;
    reload();
    var utils = {
      description: description,
      detail: detail,
      severity: severity,
      reload: reload,
      loaded: null
    };
    return utils;        

    function reload() {
       definitionsService.get().$promise.then(function(data) {
         data = data;
         if (utils.loaded && typeof utils.loaded === "function") {
           utils.loaded();
         }
       });
    }    

    function description(account) {
      var key = angular.isDefined(data.ABC[account.code]) ? account.code : '-';
      return data.IDV[key].description;
    }
}]);

To use the service in your controller, you can do so like this:

utilitiesService.loaded(function(){
    accounts[i].description = utilitiesService.description(accounts[i]);
})

Answer №2

Although this question may be old, it is still quite relevant in today's context. Building upon Florian Gl's earlier answer, if you have a service that consists of multiple functions and one or more of those functions require a preliminary "pre-service" function to be invoked (such as loading configuration information), it is best practice to move that service call to the beginning, outside of any nested functions. Below is an example dealing with the promise scenario in JavaScript:

    angular.module('gameApp')
      .factory('utilitiesService', ['definitionsService',   function(definitionsService) {

        var myFirstConfigValue = '';

        // Perform all necessary service calls here and set the variables first
        configurationService.GetConfigValue('FirstConfg')
           .then(function (response) {
                // Set the local scope variable here
                myFirstConfigValue = response;
           },
           function() { });

        function myTestFunction() {
            // Make an ajax call or something similar
            // Utilize the locally set variable here
            ajaxService.functionOneTwo(myFirstConfigValue)
               .then(response) {
                    // Handle the response accordingly
               },
               function(err) {
                  // Manage errors appropriately
                });

        }
    }]);

A crucial point to emphasize here is that when you need to load certain data, it is imperative to do so initially outside of any other functions within your service (e.g. loading JSON data).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In development, Next.js dynamic routes function correctly, but in production they are displaying a 404 error page

I am currently working on implementing dynamic routes in my Next.js project to render pages based on user input. I have set up a route that should display the page content along with the id extracted from the URL using the useRouter() hook. Everything is f ...

Creating SVG paths using coordinates for THREE.js

I copied the exact code from this ThreeJs Example designed for generating a three-dimensional City Model. I've created an SVG path outlining city boundaries using Google Maps and now I'm trying to use the above code to create a similar 3D object ...

Using Jquery to swap out div elements and reinitialize code after selecting a menu <a href>link<</a>

I have a jQuery script that swaps out a div when a href="#1" is clicked. The same link, a href="#1", is then replaced by a href="#2" and vice versa. Here is the jQuery code: $('.child2, a[href="#1"]').hide() $('#replacepagelinks a').c ...

Invoking an asynchronous method of the superclass from within an asynchronous method in the subclass

I'm currently developing JavaScript code using ECMAScript 6 and I'm facing an issue with calling an asynchronous method from a superclass within a method of an extending class. Here is the scenario I'm dealing with: class SuperClass { c ...

Obtaining the most recent commit date through the Github API

I'm in the process of creating a database containing git repositories and I'm curious about how to extract the date of the most recent commit for a repository listed in my database. My experience with the github API is limited, so I'm strug ...

Encountering an error while trying to add text: SyntaxError - Unexpected token 'for

I'm trying to print out the elements of an array using JavaScript. let listToArray = ["a","b","c"]; $(".tooltip").append(for(let i = 0; i < listToArray.length; i++) {listToArray[i]}); But I keep getting an error that says Uncaught SyntaxError: U ...

Best practices for integrating JavaScript with PHP and MySQL

When it comes to inserting data into a MySQL database from JavaScript, I typically use AJAX with jQuery's $.POST function and PHP's mysqli function. This allows me to send the data to a PHP script which then inserts it into the database. Here is ...

AngularJS is not immediately responsive to changes in $window.document.visibilityState

I am currently working with AngularJs version 1.4 and I need to be able to detect when a user is not on the tab of my app and when they return. To achieve this, I attempted using $watch in the following way: $rootScope.$watch(angular.bind($window, functio ...

Clear the cache of a query in React Query without having to fetch it again

Within my React app, I have implemented React Query in the following manner: const { data, status } = useQuery(key, queryFunc, { staleTime: 1 * 60 * 1000 }); In order to invalidate a specific key in the cache based on the value of the data, specifical ...

What are the reasons behind the lack of smooth functionality in the Bootstrap 4 slider?

My customized bootstrap4 slider is functional, but lacks smoothness when clicking on the "next" and "prev" buttons. The slider transitions suddenly instead of smoothly. Any suggestions on how to fix this? Here is the code for the slider: $('.carous ...

A Python program that creates an HTML webpage

I am currently working on a Python script that, when launched on localhost with Apache, will generate an HTML page. Here is the script (test.py): #!/usr/bin/python # -*- coding: utf-8 -*- import cgitb cgitb.enable() import cgi form = cgi.FieldStorage() ...

Obtain information through ajax using an asynchronous function

When fetching data in the first example using ajax with XMLHttpRequest, everything works smoothly. example 1 let req = new XMLHttpRequest(); req.open( "GET", "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-tempe ...

Oops! The type in React.jsx is not valid - it should be a string for built-in components. You may want to consider converting your class component to a

The error message I am encountering is as follows: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it&ap ...

Implement a dialog on top of a current web page, achieve php-ajax query result, and enhance with

My website features 'dynamic' content, where 'static' nav-buttons replace specific div contents upon clicking. While I am able to retrieve my php/ajax results in a dialog box, I am struggling with placing this dialog above my current p ...

Exchange information between two selected items

Below is a simplified version of the current code that I am working with: https://jsfiddle.net/2zauty83/8/ Javascript function checkboxlimit(checkgroup) { var checkgroup = checkgroup for (var i = 0; i < checkgroup.length; i++) { checkgroup[i] ...

Vue 3's "<Component :is="">" feature magically transforms camelCase into lowercase

Within my application, I have implemented a feature where users can customize the appearance of social media links on their page by defining which platforms they want to include. Each social media platform is represented by its own component responsible fo ...

"Encountering a problem with the Flicker API while trying to view personal

I've been attempting to retrieve my personal photos using the following function with a node package obtained from this source https://www.npmjs.com/package/flickrapi\ When trying to access pictures of another user like 136485307@N06 (Apollo Im ...

My polling operation is set up with a $timeout function, however, I am unable to successfully refresh the controller once the $timeout function has completed

I am seeking assistance with integrating the factory and controller components below. Specifically, I need guidance on referencing the factory in my controller and ensuring that the controller can access a live count from the API. Currently, I am facing a ...

How can I convert the left links in my navigation bar to a CSS drop-down menu to make it more responsive on small screens?

Here is the structure of my HTML (at the top): <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></s ...

Videos embedded using the React HTML video tag are not automatically playing on mobile devices

I have implemented a jsx variable to insert a video into my html. Despite following the advice to include muted defaultMuted, and playsinline (which I have already done), the videos autoplay on safari, chrome, and firefox on my computer but not on mobile ...