监视promise's然后error's的功能,破坏对promise的引用
Spying on promise's then error's function, breaks reference to promise
找到解决方案
Promises:转到下一个错误函数只需要重新抛出错误。
有两个按钮返回(调用)相同的承诺,一个执行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>
需要重新抛出错误。
someService.call().then(function(){
// success
}, function(e){
// error
throw e;
})
承诺:转到下一个错误函数
相关文章:
- 引用对象中的通用值
- 如何在JavaScript中将字符串转换为函数引用
- 当包含另一个asp文件时,是否也包含所有引用的样式和脚本页面
- 使用promise和mongoose对文档进行排序
- 在动态创建的元素上获取对特定选择器的引用
- IIFE中的函数引用不可用
- 如何通过引用var Using DataTables来进行分页或排序
- 如何在创建键时引用来自同一对象的键
- Datatables:通过DOM数据源中的名称引用列
- 自引用回调
- 引用类变量中的原型方法
- 无法获取属性'selectedIndex'的未定义引用或null引用
- 测试Angular Service解决错误回调中的promise
- Vanilla JS通过引用移除数组元素
- 通过引用传递JavaScript对象
- 节点协同与生成器和Promise并行流量控制
- 当您不再持有对 ES6-Promise 的引用时会发生什么情况
- Promise内部的这个上下文并没有引用内部实例
- 监视promise's然后error's的功能,破坏对promise的引用
- 在promise-chain中传递引用函数的值