Promises : go to next error function 只需要重新抛出错误。
为什么承诺的参考在侦察时不会执行当时的错误功能?
有两个按钮返回(调用)相同的promise,一个执行ok($ scope.expected() - 按钮呈现红色),其他进入成功函数($ scope.notExpected() - 按钮呈现绿色)并且它是不期望的行为。
当前的解决方案是,包装另一个承诺;
var app = angular.module('thenApp', []);
function ThenCtrl($scope, thenService, $q) {
$scope.expected = function() {
return thenService.doIt()
.then(function() {
console.log('was a success');
});
};
$scope.notExpected = function() {
return thenService.doIt()
.then(function() {
console.log('was a success');
}, function() {
console.log('has failed');
});
};
$scope.solution = function() {
var deferred = $q.defer();
thenService.doIt()
.then(function() {
deferred.resolve();
console.log('was a success');
}, function() {
deferred.reject();
console.log('has failed');
});
return deferred.promise;
};
}
app.controller('ThenCtrl', ThenCtrl);
var CLICK_EVENT = 'click';
var TIMEOUT_TO_END_ANIMATION = 1000;
var SUCCESS_CLASS = 'btn-success success';
var FAIL_CLASS = 'btn-error error';
var LOADING_CLASS = 'loading';
/**
* Inspiration from https://github.com/johannesjo/angular-promise-buttons
* @param $parse
* @param $timeout
* @returns {{scope: {promise: string, stateRedirect: string}, link: link}}
*/
function btnLoader($parse, $timeout) {
return {
restrict: 'A',
require: '?ngClick',
scope: true,
link: function(scope, el, attrs) {
el.addClass('btn-load');
var promiseWatcher;
// we need to use evalAsync here, as
// otherwise the click or submit event
// won't be ready to be replaced
scope.$evalAsync(function() {
var cb = $parse(attrs.ngClick);
function buttonLoader() {
// Make sure we run the $digest cycle
scope.$apply(function() {
var promise = cb(scope.$parent, {
$event: CLICK_EVENT
});
// only init watcher if not done before
if (!promiseWatcher) {
// watch promise to resolve or fail
promiseWatcher = scope.$watch(function() {
return promise;
}, function(nVal) {
// for regular promises
if (nVal && nVal.then) {
el.unbind(CLICK_EVENT);
el.addClass(LOADING_CLASS);
el.removeClass(SUCCESS_CLASS);
el.removeClass(FAIL_CLASS);
nVal.then(function() {
// promise was a success
el.addClass(SUCCESS_CLASS);
if (attrs.alwaysBind) {
el.bind(CLICK_EVENT, buttonLoader);
}
}, function() {
// promise was a fail
el.addClass(FAIL_CLASS);
el.bind(CLICK_EVENT, buttonLoader);
}).finally(function() {
el.removeClass(LOADING_CLASS);
promiseWatcher();
promiseWatcher = null;
$timeout(function() {
el.removeClass(SUCCESS_CLASS);
el.removeClass(FAIL_CLASS);
}, TIMEOUT_TO_END_ANIMATION);
});
}
});
}
});
}
// unbind original click event
el.unbind(CLICK_EVENT);
// rebind, but this time watching it's return value
el.bind(CLICK_EVENT, buttonLoader);
});
}
};
}
app.directive('btnLoader', btnLoader);
function thenService($q, $timeout) {
thenService.doIt = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.reject(null);
}, 500);
return deferred.promise;
};
return thenService;
}
app.factory('thenService', thenService);

.loading {
background: yellow !important;
}
.btn-error {
background: red !important;
}
.btn-success {
background: green !important;
}
.btn {
margin-bottom: 20px;
border: 1px solid rgba(0, 0, 0, 0.3);
background: white;
width: 250px;
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
}
.btn:hover {
background: lightgray;
cursor: pointer;
}

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="thenApp" ng-controller="ThenCtrl">
<p>
Button action does not spy on then's error function.
</p>
<div class="btn" btn-loader="" always-bind="true" ng-click="expected()">
As expected
</div>
<p>
Button action spies on then's error function.
</p>
<div class="btn" btn-loader="" always-bind="true" ng-click="notExpected()">
Not expected
</div>
<p>
Solution for spying on then's error function.
</p>
<div class="btn" btn-loader="" always-bind="true" ng-click="solution()">
Solution
</div>
</div>
&#13;
答案 0 :(得分:0)
需要重新抛出错误。
someService.call().then(function(){
// success
}, function(e){
// error
throw e;
})