Верижни .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>

Разгледах подобните въпроси, но не мога да намеря разликата между моя подход и този в приетите отговори (напр. това един)


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


Отговори (1)


Това е така, защото започвате веригата си с $.Deferred().resolve(), което е обещание на jQuery. Обещанията на jQuery не отговарят на стандарта Promises/A+ (Все още!) и следователно не обработват правилно грешките. Вижте този въпрос и отговор за повече подробности.

Простото решение би било просто да не обвивате кода си в отложен jQuery. Ако искате празно разрешено обещание, можете вместо това да използвате $q.when() на Angular.

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