Search code examples
javascriptangularjspromiseangular-promisees6-promise

Second call to promise executes before the promise returns - Angular Javascript


I have the following pattern of code, where an update call is made each time the user updates the data on the view.

// FACTORY SERVICE CODE
.factory('updateService', ['$http', '$q', function($http, $q){
    var df = $q.defer();
    var updateData = function(uriName, dataObj){
        $http({
          method: 'PUT',
          data: dataObj,
          url: uriName
            }).then(function successCallback(response) {
                console.log('from put');
                console.log(response.data);
                df.resolve(response.data);
            }, function errorCallback(response) {
                console.log('Error', response.data);
                df.reject(response.data);
        });
        return df.promise;
    }
    return {updateData:updateData};
}])

// CONTROLLER CODE
.controller('MainCtrl', ['$scope','updateService', function($scope, updateService) {
    $scope.saveToServer = function(){
        var tmpObj = {data: $scope.dataOne, anotherData: $scope.dataTwo};
        myService.updateData(uriName, tmpObj).then(function(resolved) {
            console.log('CONTROLLER');
            $scope.myData = resolved;
            console.log($scope.myData);
            console.log('end');
        }, function(rejected){
            console.log('put rejected');
        });
    });
    $scope.btnUpdateClick = function(){
        $scope.saveToServer();
    };
}]);

PROBLEM: When the user makes an update request for the first time, the code works as expected. But when the user updates therein after, the "resolved promise" code (in the controller) executes FIRST and then the $http code (in the service) executes.

SAMPLE OUTPUT of btnUpdateClick made TWICE with enough interval in-between:

from put
Array [ Object, Object]
CONTROLLER
Array [ Object, Object]
end
CONTROLLER
Array [ Object, Object]
end
from put
Array [ Object, Object]

QUESTION: Kindly point me out where I'm making a mistake?

Is the problem because of PUT request?

or is it possible to correct the execution queue as expected, through $apply or anything like that?


Solution

  • Start the promise every time you call a function like below:

    .factory('updateService', ['$http', '$q', function($http, $q){
    
        var updateData = function(uriName, dataObj){
            var df = $q.defer(); //Changes here
            $http({
              method: 'PUT',
              data: dataObj,
              url: uriName
                }).then(function successCallback(response) {
                    console.log('from put');
                    console.log(response.data);
                    df.resolve(response.data);
                }, function errorCallback(response) {
                    console.log('Error', response.data);
                    df.reject(response.data);
            });
            return df.promise;
        }
        return {updateData:updateData};
    }])
    

    In this way you are creating a new promise on every function call.