根据我最近的其他问题,我试图将数据保存到服务器以获取针对移动设备(不稳定连接)的角度应用程序,因此它应该继续尝试请求直到成功。
我怎么能用承诺做到这一点?
目前我已经:
服务
this.addObject = function addObject(object) {
var deferred = $q.defer();
var httpConfig = {
method: 'POST',
url: 'http://api.foo.com/bar',
data: object
}
setTimeout(function() {
$http(httpConfig).
success(function(data, status) {
deferred.resolve('Woohoo!');
}).
error(function(data, status) {
deferred.reject('Couldnt reach server this time...');
});
}, 3000);
return deferred.promise;
}
控制器:
myService.addObject(myObject)
.then(function(message) {
console.log(message);
}, function(message) {
console.log(message);
});
我无法删除拒绝回调,因为代码似乎在没有它的情况下执行,但是一旦调用了拒绝,它就会破坏setTimeout循环。在成功回调之前,我如何强制承诺重复?
答案 0 :(得分:3)
这是AngularJS service retry when promise is rejected
的答案的正确形式 this.addObject = function addObject(object) {
var counter = 0;
var deferred = $q.defer();
var httpConfig = {
method: 'POST',
url: 'http://api.foo.com/bar',
data: object
}
var doRequest = function() {
counter++;
var self = this,args = arguments;
$http(httpConfig).
success(function(data, status) {
deferred.resolve('Woohoo!');
}).
error(function(data, status) {
//just fail already, it's not working
if(counter > 5) {
return deferred.reject('Couldnt reach server this time...');
}
//this will re-call doRequest();
args.callee.apply(self);
});
}
doRequest();
return deferred.promise;
}
答案 1 :(得分:0)
当您使用$http
时,http拦截器可以执行此操作。如果您希望http请求无限循环,直到它返回成功:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('RetryInterceptor');
}]);
app.factory('RetryInterceptor', function($timeout, $injector) {
return {
'responseError': function(rejection) {
// Manual inject to work around circular dependency issue
var $http = $injector.get('$http');
return $timeout(function() {
return $http(rejection.config);
},3000);
}
}
});
这是因为对$ http的初始调用在(在这种情况下)所有的responseError拦截器都已解决后才会解析。
您可以在http://plnkr.co/edit/QAa9oIK4lTM6YwccEed3?p=preview看到这一点(在控制台日志中查看每3秒发生一次失败的请求。)
注意:可能需要更多逻辑来确保它只在正确的错误上重试。例如,它不是真正的404,实际上浏览器应该受到指责。
答案 2 :(得分:0)
它应该继续尝试请求,直到成功。我怎么能用承诺做到这一点?
通过“递归”在错误处理程序中再次调用该函数,以便您使用下一次尝试的结果解析promise。
this.addObject = function addObject(object) {
var httpConfig = {
method: 'POST',
url: 'http://api.foo.com/bar',
data: object
}
return $http(httpConfig).then(function(data, status) {
return 'Woohoo!';
}, function(data, status) {
throw 'Couldnt reach server this time...';
});
}
this.addObjectForever = function addObject(object) {
var that = this;
return this.addObject(object).then(null, function(err) {
console.log("Failed this time");
return $timeout(3000).then(function() {
console.log("Trying again now");
return that.addObjectForever(object);
});
});
};
instance.addObjectForever(obj).done(function() {
console.log("It eventually worked");
});
答案 3 :(得分:0)
这里非常拥挤:) 我的解决方案:
angular.module('app', [])
.service('Service',function($q,$http) {
this.addObject = function(object) {
var httpConfig = {
method: 'POST',
url: 'http://api.foo.com/bar',
data: object
}
var deferred = $q.defer();
$http(httpConfig)
.success(function(data, status) {
deferred.resolve('Woohoo!');
})
.error(function(data, status) {
deferred.reject('Couldnt reach server this time...');
});
return deferred.promise;
};
})
.controller('MainCtrl',function($scope,$interval,Service){
/*Service.addObject({})
.then(function(message) {
console.log(message);
}, function(message) {
console.log(message);
});*/
$interval(function(){
Service.addObject().then(function(message) {
console.log(message);
}, function(message) {
console.log(message);
});
},1000);
})
答案 4 :(得分:0)
嗯。即使有针对此特定情况的HTTP拦截器,使用promises而不是回调的优点之一是您可以使用更高阶函数。
// both p and q are functions that create a promise
p = makeSomePromise(options)
q = repeat(10, p)
也就是说,例如,一个函数采用承诺生成函数并生成一个新的承诺生成函数,重复重试另一个函数,直到最大。 / p>
例如:(这是针对使用kew
的nodeJS,但你应该明白这一点)
var Q = require('kew');
function retryPromise(n, mkPromise) {
if(n > 0)
return mkPromise()
.fail(function(){
console.log('failed promise, retrying maximum ' + n + ' more times');
return retryPromise(n - 1, mkPromise);
});
return mkPromise();
}
(function(){
var mkOp = function(){
if(Math.random() > .1)
return Q
.fcall(function(){return 1;})
.then(function(){throw Error('aah');});
return Q.fcall(function(){return 'yay'});
};
retryPromise(10, mkOp)
.then(function(data){
console.log(data);
})
.fail(function(err){
console.log('failed', err);
});
}());