Struggling with grasping the concept of promises in AngularJS

I encountered a challenge while working with AngularJS & REST. My data service was not returning data in time for my model to use, despite implementing a promise.

I would greatly appreciate any assistance from those more knowledgeable on this matter.

In my routing, a booking Id is passed to the bookingController. This controller retrieves booking details and displays them in an editable form in the booking.html template.

testLabApp.controller('bookingController', function ($q, $scope, $location, $window, $routeParams, service) {
if ($routeParams.id) {
    $scope.bId = $routeParams.id;

    // I set up a promise here
    var bookdefer = $q.defer();
    bookdefer.promise
        .then(function (booking) {

            $scope.booking = booking;

            $scope.editableBooking = angular.copy($scope.booking);

            console.log("[bookingCtrl] 1 New: " + $scope.booking.Storeno + " and Editable: " + $scope.editableBooking.Storeno);
        });

    bookdefer.resolve(service.getBooking($scope.bookingId));

}
else {
    //...
}

When the code reaches '[bookingCtrl] 1...', it throws an error "TypeError: Unable to get property 'Storeno' of undefined or null reference," indicating that the booking data may not have been retrieved yet.

The console then shows:

[getBooking] Done = Id: 209 | Store no: 9180 | Description: test | Status: Booked

My data service consists of functions that make REST calls:

testLabApp.factory('service', ['$rootScope', '$http', function ($rootScope, $http) {
    var service = {};

    $http({
        method: 'GET',
        url: "/_api/web/lists/GetByTitle('Bookings')/Items?$filter=Id eq '" + bookingId + "'",
        headers: {
            'Accept': 'application/json; odata=verbose'
        },
    }).success(function (d) {
        var e = d.d.results[0];
        booking = {
            Id: e['Id'],
            Storeno: e['Title'],
            BookedBy: e['BookedBy'],
            Description: e['Description'],
            StartDate: e['StartDate'],
            EndDate: e['EndDate'],
            Status: e['Status']
        };
        console.log("[getBooking] Done = Id: " + booking.Id + " | Store no: " + booking.Storeno + " | Description: " + booking.Description + " | Status: " + booking.Status);

        return booking;

    }).error(function (er) {
        console.log("[getBooking] http error : " + er);
    });
};

Any guidance or suggestions would be highly appreciated.

Regards, Craig

Answer №1

When the success function of your service is triggered asynchronously, it results in null being returned to the controller. In all of my Angular projects, I have implemented the following approach:

service.fetchData = function(id) {
    var deferred = $q.defer();

    $http({
        method: 'GET',
        url: '/api/some-end-point/id'
    }).then(function(response) {
        var result = response.data;
        deferred.resolve(result);
    }, function(error) {
        $log.error(error);
        deferred.reject(error);
    });
    return deferred.promise;
}

The controllers are structured as follows:

if ($routeParams.id) {
    $scope.itemId = $routeParams.id;

    //Expecting this line to initiate the promise
    service.fetchData($routeParams.id).then(
        function(response){
            $scope.item = response;
        },
        function(error){
            console.log(error);
        }
    );
}

Answer №2

'Here is a sample of an asynchronous GET request made from a controller using a service. Instead of creating a new deferred object, you can simply return $http.get() to your controller:

(function(){

  angular.module('app', []);


  angular.module('app').factory('service', ['$http', function($http){

    return {
      fetchData: fetchData;
    }

    function fetchData(){
      return $http.get('/url')
        .success(function(data){
          //Implement business logic here
          return data;
        })
        .error(function(error){
          return error;
        });
    }

  }]);

  angular.module('app').controller('controller', ['$scope', 'service',  function($scope, service){

    service.fetchData()
      .then(function(response){
        $scope.data = response.data;
      })
      .catch(function(error){
        //Handle errors here
      });
  }]);

})();

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

Error Alert: Invalid Hook Call detected while using the useSelector hook within a Functional Component

I am encountering an error Error: Invalid hook call. Hooks can only be called inside of the body of a function component. The versions of React and the renderer (such as React DOM) might not match There could be violations of the Rules of Hooks Multiple ...

Choosing a request date that falls within a specified range of dates in PHP Laravel

In my database, I currently store two dates: depart_date and return_date. When a user is filling out a form on the view blade, they need to select an accident_date that falls between depart_date and return_date. Therefore, before submitting the form, it ne ...

Storing array values in a MySQL database within the Laravel framework

I am currently working on developing a REST API in Laravel. I am facing an issue where I need to post array data into the database, but I am unsure of how to do it. Can anyone provide guidance on this? I am new to Laravel. ProductdetaisController.php < ...

What is the process of creating and customizing popovers in Bootstrap 5 with jquery?

Is there a way to dynamically create and add content to Bootstrap 5 popovers using JavaScript or jQuery? In Bootstrap 3, I used the following method: $('#element').popover({ placement : 'left', trigger : 'focus', html: true } ...

Managing the transition of the object in question

I am in the process of designing a navigation bar. I have created an array to store the information of the tabs present in the nav bar. tabs: [ { name: 'All',id: "dash.courses.all", to: 'all', curre ...

I encountered an issue when attempting to execute an action as I received an error message indicating that the dispatch function was not

I just started learning about redux and I am trying to understand it from the basics. So, I installed an npm package and integrated it into my form. However, when I attempt to dispatch an action, I encounter an error stating that 'dispatch is not defi ...

Displaying elapsed time in JavaScript (Node.js)

Looking for a way to convert a date time or time-stamp format like 2015-12-18 07:10:54 into a relative time, such as "2 hours ago." I attempted the code provided, but it seems to consistently show an incorrect estimation of "8 days ago." function convert ...

Mistake in Resource URL for BreezeJS using C# WebAPI with OData

My project setup involves using BreezeJS/Angular/WebAPI(OData) to make GET calls like this: breeze.EntityQuery .from(resource) .using(manager) .execute() .then(function (data) { deferred.resolve(da ...

Applying specific style properties in styled-components can vary based on certain conditions

Is it possible to apply multiple properties at once? const Button = styled.div` color: blue; opacity: 0.6; background-color: #ccc; ` I want to apply styles for the active state without having to specify conditions for each property individually. Ho ...

Transform a checkbox input into two distinct buttons

I am trying to change the input checkbox that toggles between light and dark mode into two separate buttons. How can I achieve this functionality? Check out the demo here: https://jsfiddle.net/ot1ecnxz/1 Here is the HTML code: <input type="checkb ...

Having trouble with Vuejs Ternary Operator or Conditional in v-bind-style?

Having some unexpected issues while trying to implement a style conditional for items in Vuejs. I have come across Stack Overflow posts on how to use a ternary, either through an interpolated string or a computed style object. I've attempted both met ...

I was unable to produce the result of the input value entered at the bottom

Is there a way to view the input and output simultaneously in my project? I've seen this done using a button, but I'm looking to achieve the same without a button. How can I do this? <input type="text" id="myText"> <b ...

What are the steps to make a basic slider with jQuery without using plugins?

<script> const animateImages = function(){ $("#slider").animate({"left":"-=1775px"},10000,function(){ $("#slider").animate({"left":"0px"},10000); animateImages(); }); }; animateImages(); </script> I incor ...

Having trouble with the rendering of the Stripe Element Quickstart example

Currently, I am diving into the world of Stripe's Element Quickstart. Take a look at this fiddle that I have been working on. It seems to be quite different from the example provided. Although I have included the file, I can't seem to figure out ...

Guidelines on incorporating a dynamically selected option into a dynamically populated dropdown menu

I have a challenge where I need to dynamically set the selected option text for a select menu based on the 'location' parameter passed into the 'updateDepartment' function. This parameter is obtained from a previous PHP request. The AJ ...

Could offering a Promise as a module's export be considered a legitimate approach for asynchronous initialization in a Node.js environment?

I am in the process of developing modules that will load data once and create an interface for accessing that data. I am interested in implementing asynchronous loading of the data, especially since my application already utilizes promises. Is it considere ...

Highcharts introduces shared tooltips for specific data series

I am seeking to implement specific behavior in highcharts regarding tooltips. The desired setup includes having two types of tooltips: the default shared tooltip a custom tooltip For the custom tooltip, a simple formatter can be utilized. However, the c ...

Saving the state of checkboxes in Angular Material

I am trying to figure out a solution for storing checkbox values, specifically whether they have been checked before or not. For example, I have this dialog: https://i.sstatic.net/c16Ju.jpg After clicking on a checkbox and then clicking Save, the checkbox ...

JS How can I generate individual buttons in a loop that trigger separate actions?

Currently, I am working with loops in jQuery to create a series of boxes that contain specific values. The problem arises when I try to assign actions to each box based on the values from an array. For example, I want each box to trigger a different alert ...

Does Objective C have a counterpart to the encode() method in JavaScript?

NSString *searchString = @"Lyngbø"; NSLog("%@",[searchString stringByAddingPercentEscapeUsingEncoding:NSUTF8StringEncoding]); The result is: Lyng%C3%B8 <script type="text/javascript"> document.write(escape("Lyngbø")); </script> The result ...