我有以下链式承诺序列:
$scope.promisesInProgress = true
myService.myFirstPromise(id)
.then(function(data){
$scope.firstResponse = data;
return myService.mySecondPromise(id);
})
.then(function(data){
$scope.secondResponse = data;
})
.finally(function(){
$scope.promisesInProgress = false;
});
无论前两个承诺的成功/失败是什么,最终都会调用finally()
回调函数?
例如,如果myFirstPromise()
返回400响应,则永远不会调用mySecondPromise()
- 但我认为仍然会抛出finally()
块?如果mySecondPromise()
返回400(并且永远不会设置$scope.secondResponse
)并且两个promises都返回200,那么同样如此。
答案 0 :(得分:2)
Angular 1.x $q
服务受Kris Kowal的Q启发,基于docs:
finally(callback,notifyCallback) - 允许您观察承诺的履行或拒绝,但是在不修改最终值的情况下这样做。无论承诺被拒绝还是已解决,这对于释放资源或进行必要的清理都非常有用。有关详细信息,请参阅完整规范。
是的,无论myFirstPromise
已解决或拒绝,finally()
块始终会被调用
更新
要注意,在finally()
解决(或拒绝)之前会调用myFirstPromise
mySecondPromise
块,因为myFirstPromise
和mySecondPromise
是不同的承诺实例,mySecondPromise
在myFirstPromise
已解决
答案 1 :(得分:1)
我编写了一个Jasmine测试,看看是否在每个函数执行时调用finally()
块,无论链接的promise返回什么。
describe('myController Test Suite', function(){
var q, scope, deferred, myService;
// Initialize the Pointivo module
beforeEach(function(){
module('myApp');
});
// Mock out fake service
beforeEach(function(){
myService = {
myFirstPromise: function(){
deferred = q.defer();
// TEST ME
deferred.resolve('first promise response');
return deferred.promise;
},
mySecondPromise: function(){
deferred = q.defer();
// TEST ME
deferred.resolve('second promise response');
return deferred.promise;
},
myThirdPromise: function(){
deferred = q.defer();
// TEST ME
deferred.resolve('third promise response');
return deferred.promise;
}
};
spyOn(myService, 'myFirstPromise').and.callThrough();
spyOn(myService, 'mySecondPromise').and.callThrough();
spyOn(myService, 'myThirdPromise').and.callThrough();
});
// Assign controller scope and service references
beforeEach(inject(function($controller, $rootScope, $q){
scope = $rootScope.$new();
q = $q;
$controller('myController', {
$scope: scope,
myService: myService
});
}));
describe('finally test', function(){
it('should always hit the finally statement', function(){
scope.finallyStatementFlag = false;
scope.test();
scope.$apply();
expect(scope.finallyStatementFlag).toBeTruthy();
});
});
});
以上基于控制器的假设:
myApp.controller('myController', function($scope, myService){
$scope.finallyStatementFlag = false;
$scope.test = function(){
myService.myFirstPromise()
.then(function(data){
console.log(data);
return myService.mySecondPromise()
})
.then(function(data){
console.log(data);
return myService.myThirdPromise();
})
.then(function(data){
console.log(data);
})
.finally(function(){
console.log('finally statement');
$scope.finallyStatementFlag = true;
});
}
});
即使您在我们定义deferred.resolve()
的{{1}}回调中更改了deferred.reject()
到beforeEach()
中的任何一个或全部,上述内容也会通过。