Цепочка вызовов .then(): отклонение не распознано

Мне трудно понять идею промисов (в angularjs).

Я подумал, что могу определить функцию, которая возвращает обещание. Потребитель этого обещания может работать с ним и также может возвращать некоторые данные или обещание.

Но этот простой пример ведет себя неожиданно: первый вызов .then() возвращает отказ, а второй вызов then() выполняет функцию успеха.

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>

Я просмотрел похожие вопросы, но не могу найти разницу между моим подходом и подходом в принятых ответах (например, this один)


person Christopher    schedule 04.05.2015    source источник


Ответы (1)


Это потому, что вы начинаете свою цепочку с $.Deferred().resolve(), что является обещанием jQuery. Промисы jQuery не соответствуют стандарту Promises/A+ (пока!) и поэтому неправильно обрабатывают ошибки. Подробнее см. этот вопрос и ответ.

Простое решение было бы просто не оборачивать ваш код в jQuery deferred. Если вам нужно пустое разрешенное обещание, вы можете вместо этого использовать Angular $q.when().

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>

person Benjamin Gruenbaum    schedule 04.05.2015