0

I m reaching out to you to get assistance on the $promise issue with AngularJS.

Here is the documentation information on $resource and it will be applicable to $http as well

link

Having said that, I m trying to make an API call and on success want to perform callback action. Since the operation takes place asynchronously, callback action takes place even before the API call gets completed. This leads to incorrect data reflection. Here is the simple get example, using $resource and $http. In both the cases the actual expectation is that console log should show the actual data but it shows the promise data and resulting in the callback function getting called even before the API calls get completed

$http.get('../../../Employee/GetEmployees').success(function (data) {
        console.log(data);
    });


   return $resource('../../../Employee/GetEmployees', {},
        {
            query: { method: 'GET', isArray: true },
        });

I have provided the example just for giving the clear picture but my actual problem comes with “PUT”(Update). As per the logic, update has to take place first through API call and then the page needs to be redirected to the List page where the updated data will be queried and rendered. Any recommendation on this will be greatly appreciated.

 $scope.UpdateEmp = function () {
        var empl = $scope.Employee;
        empFactory.empUpdate.update({ EmpID: $routeParams.EmpID, empval: empl }).$promise.then(function () { // update method in my resource uses $resource
            $location.path('/EmpList'); //redirect to list
        });

P.S: For time being, please leave about the URL, please visualize it as an API which returns JSON object.

Here is the complete code

Here is the complete code.

Routing:

var myApp = angular.module('myApp', ['emp', 'ngRoute']);

myApp.config(function ($routeProvider) {

    $routeProvider
        .when('/',
        {
            templateUrl: 'pages/EmpList.html',
            controller: 'empController'
        }
        )
    .when('/EmpDetail/:EmpID',
    {
        templateUrl: 'pages/EmpDetail.html',
        controller: 'empDetailController'
    }
)
     .when('/EmpList',
    {
        templateUrl: 'pages/EmpList.html',
        controller: 'empController'
    }
    )
     .when('/EmpCreate',
    {
        templateUrl: 'pages/EmpCreate.html',
        controller: 'empCreateController'
    });

});

Here is the controller method

    myApp.controller('empController', function ($scope, $routeParams, $location, empFactories, empFactory, $http, empHttpFactory) {

            $scope.Employees = empFactories.query();

            $scope.edit = function (EmpID) {
            $location.path('/EmpDetail/' + EmpID);
        };


        $scope.Delete = function (empID) {
            empFactory.empDelete.del({ EmpID: empID }, function () {
                $location.path('/EmpList');
            });
        }

        $scope.Createnew = function () {
            $location.path('/EmpCreate');
        }


    });

    myApp.controller('empDetailController', function ($scope, empFactory,empFactories, $routeParams, $location) {

        $scope.Employee = empFactory.employee.show({ EmpID: $routeParams.EmpID });

        console.log($scope.Employee);

        $scope.UpdateEmp = function () {
            var empl = $scope.Employee;
            empFactory.empUpdate.update({ EmpID: $routeParams.EmpID, empval: empl }).$promise.then(function () { // update method in my resource uses $resource
                $location.path('/EmpList'); //redirect to list
            }); 

        };

    });

Here is the service

var myservice = angular.module('emp', ['ngResource', 'ngRoute']);
myservice.factory('empFactories', function ($resource) {
    return $resource('../../../Employee/GetEmployees', {},
        {
            query: { method: 'GET', isArray: true },
            create: { method: 'POST' }
        });
});

myservice.factory('empFactory', function ($resource) {



    //return $resource('../../Employee/GetEmployee/:EmpID', { EmpID: '@EmpID' },
    //      {
    //          show: { method: 'GET' }
    //      });


    var resource = {
        employee:
            $resource('../../Employee/GetEmployee/:EmpID', { EmpID: '@EmpID' },
           {
               show: { method: 'GET' }

           }),
        empUpdate:
            $resource('../../Employee/PutEmployee/:EmpID', { EmpID: '@EmpID', empval: '@empl' }, { update: { method: 'PUT', isArray: true } }),
        empDelete:
            $resource('../../Employee/DeleteEmployee/:EmpID', { EmpID: '@EmpID' }, { del: { method: 'DELETE', isArray: true } }),

        empCreate:
            $resource('../../Employee/CreateEmployee', { empval: '@empl' }, { create: { method: 'POST', isArray: true } })
    }

    return resource;
});
4
  • Are you able to post full code or check request & response from developer tools ? I found it strange that success run before response received. Commented May 20, 2015 at 2:50
  • For the get method, I m checking in developer tools console log.. For Put method, as I stated, the expectation was "redirection should take place after the update". I have used similar onsuccess condition for Put as well as you could see in my example Commented May 20, 2015 at 2:53
  • I know that you are trying to keep the question concise, but I have trouble understanding how $http call is related to return $resource() - are these just alternatives in your API? And how both are related to the call made within UpdateEmp function Commented May 20, 2015 at 2:56
  • I posted the complete code in the below answer section. Just for example, I compared $http and $resource. I m using $resource only. Just to ensure that I should not get the comments as , this problem will not occur in $http, I shared the example. Commented May 20, 2015 at 3:01

3 Answers 3

0

First i see a design problem, your factory shouldn't return resources, should return promises,

myservice.factory('empFactory', function ($resource) {

  var employeeResource  = $resource('../../Employee/GetEmployee/:EmpID', { EmpID: '@EmpID'}, {show: { method: 'GET' } }),
  updateResource = $resource('../../Employee/PutEmployee/:EmpID', { EmpID: '@EmpID', empval: '@empl' }, { update: { method: 'PUT', isArray: true } }),
  deleteResource = $resource('../../Employee/DeleteEmployee/:EmpID', { EmpID: '@EmpID' }, { del: { method: 'DELETE', isArray: true } }),
  createResource = $resource('../../Employee/CreateEmployee', { empval: '@empl' }, { create: { method: 'POST', isArray: true } });

  return { 
    getEmployee: function(id){
      return employeeResource.get({EmpID: id}).$promise;
    },
    updateEmployee: function(){
      return updateResource.update(...).$promise;
    }
  };
});

I think that the problem is that you are calling

$scope.Employee = empFactory.employee.show({ EmpID: $routeParams.EmpID });

This returns a resource right now, so you are not technically obtaining the employee anywhere. Is not very clear where is the error, are you trying to execute several resource request in parallel? if that's it use $q.all([asyncCall1,asyncCall2,...]).spread(function(r1, r2, ...) {...});

Regards

Sign up to request clarification or add additional context in comments.

5 Comments

problem is with my update statement, $scope.UpdateEmp = function () { var empl = $scope.Employee; empFactory.empUpdate.update({ EmpID: $routeParams.EmpID, empval: empl }).$promise.then(function () { // update method in my resource uses $resource $location.path('/EmpList'); //redirect to list }); Here even before , I obtain the response, redirection takes place
How do you known that the "response isn't there yet" ? You are not obtaining the parameter in the $promise.then(function(response){...//redirect}) You are not using the response, or are you catching the result somewhere else?
Ok.. I m doing an update to my model in the update call. and when the redirect occurs, my expectation was it queries the updated model and returns it.. Once the page is redirected, my model collection is queried and populates the list page.
I think you got several issues there, empController is never requesting the list of employees. If you updates yor model from empDetailController, is not the same has update the model on empController. I recommend you to use ui-router and instead of $location.path('/') use $state.go('empList',{//data}) and in your empController you can use $stateParams to obtain the data sent the state change, or even better when you define your state you can add a resolve field which can contain a promise to ve solved before the state change
you got the problem correctly and ur solution sounds more logical as well. Could you please provide me a working sample of it so that I can test it. My apologize, I m new to this angular part.
0

With $resource you define the API route and the parameters the API needs in order to process the request. Then, later you will need to supply the $resource with data and perform an action (get, save, query, remove, delete).

I personally prefer to work with $http as it's pretty cut and dry. The down-side is you can't pre-define the routes and parameters across your app.

Here's a pen that shows you both $resource and $http requests.

http://codepen.io/kenhowardpdx/pen/BNzXeE

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

MyService.$inject = ['$http', '$resource'];
function MyService ($http, $resource) {
    var _this = this;

    var Search = $resource('http://www.omdbapi.com/?tomatoes=true&plot=full&t=:searchTerm', {searchTerm:'@searchTerm'});

    _this.httpSearch = function (searchTerm) {
        return $http.get('http://www.omdbapi.com/?tomatoes=true&plot=full&t=' + searchTerm);
    };

    _this.resourceSearch = function (searchTerm) {
        return Search.get({searchTerm: searchTerm}).$promise;
    }
}

angular.module('app').service('MyService', MyService);

MyController.$inject = ['MyService'];
function MyController (MyService) {
    var _this = this;

    _this.type = 'http';

    _this.searchFilms = function () {
        if (_this.type === 'http') {
            MyService.httpSearch(_this.searchTerm).then(function(_response) {
               _this.results = _response.data; 
            });
        } else {
            MyService.resourceSearch(_this.searchTerm).then(function(_response) {
               _this.results = _response; 
            });
        }
    }
}

angular.module('app').controller('MyController', MyController);`

Comments

0

factory does not need to return a promise.I mean that depends on how you manage your factory and controllers and how you are going to resolve it.

your factory does not return a promise but resource, so it should be resolved in your controller. your update method in controller should be like this :

    $scope.UpdateEmp = function () {
    var empl = $scope.Employee;
    empFactory.empUpdate.update({ EmpID: $routeParams.EmpID, empval: empl }, function (successResponse) { // update method in my resource uses $resource
        $location.path('/EmpList'); //redirect to list
    },function (error) { 
     // do something on error callback
    });

read about angularjs resource angularjs docs about $resource

2 Comments

Thanks @konammagari . The problem here is, its not making calls to my API controller to get the updated list of employees. Only for the first time, the call is made to get the data and from the next call to my API controller, control is not going to get the updated list
Please see the response from Matho in the next answer section. I m going through exact same issue as what he has defined. Also if you share your email ID/phone number, it would be great to connect with you for angular queries

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.