1

I'm having a difficult time understanding the idea of promises (in angularjs).

I thought that I could define a function that returns a promise. The consumer of this promise can work with it, and might return some data or a promise as well.

But this simple example behaves unexpectedly: The first .then() call returns a rejection, yet the second then() call executes the success function.

angular.module('myexample', []).controller('Ctrl', ['$scope', '$q',
  function($scope, $q) {
    $scope.sdfsdf = "";
    $scope.action = function() {
      $('#msg').html("");
      $.Deferred().resolve()
        .then(function(response) {
          $('#msg').html("error during processing of data!");
          return $q.reject('my-failure-reason');
        })
        .then(
          function(data) {
            $('#msg').html($('#msg').html() + "<br>success: " + data);
          },
          function(data) {
            $('#msg').html($('#msg').html() + "<br>failure: " + data);
          }
        );
    };
  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body ng-app="myexample">
  <div ng-controller="Ctrl">
    <button ng-click="action()">Go!</button>
    <div id="msg"></div>
  </div>
</body>

I had a look at the similiar questions, but I can't find the difference between my approach and the one in the accepted answers (e.x. this one)

Community
  • 1
  • 1
Christopher
  • 2,005
  • 3
  • 24
  • 50

1 Answers1

2

This is because you're starting your chain with $.Deferred().resolve() which is a jQuery promise. jQuery promises do not conform to the Promises/A+ standard (Yet!) and thus do not handle errors correctly. See this question and answer for more details.

The simply solution would simply be not to wrap your code in a jQuery deferred. If you want an empty resolved promise you can use Angular's $q.when() instead.

angular.module('myexample', []).controller('Ctrl', ['$scope', '$q',
  function($scope, $q) {
    $scope.sdfsdf = "";
    $scope.action = function() {
      $('#msg').html("");
      $q.when() // not jQuery
        .then(function(response) {
          $('#msg').html("error during processing of data!");
          return $q.reject('my-failure-reason');
        })
        .then(
          function(data) {
            $('#msg').html($('#msg').html() + "<br>success: " + data);
          },
          function(data) {
            $('#msg').html($('#msg').html() + "<br>failure: " + data);
          }
        );
    };
  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body ng-app="myexample">
  <div ng-controller="Ctrl">
    <button ng-click="action()">Go!</button>
    <div id="msg"></div>
  </div>
</body>
Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504