我正在尝试抽象下面的函数,以便我可以轻松地重用。函数基本上运行一个给定的函数,该函数最多返回5次promise或者直到promise被解析。 DataFn让我特别难过。它返回一个promise,但是当第一次失败后第二次执行run函数时,它不再尝试连接到服务器。如果我对其工作的函数名称进行硬编码,但作为传递的参数仅在开始时起作用。
var persistentPromise = (function() {
var maxRetries = 0;
return function run(dataFn, messageObject) {
var deferred = $q.defer();
dataFn.$promise.then(function (response) {
deferred.resolve(response);
},
function (response) {
if(response == 503) {
if(++maxRetries < 6) {
messageService.emit(messageObject.warning);
$timeout(function () {
run(dataFn, messageObject);
}, 10000);
} else {
messageService.emit(messageObject.end);
deferred.reject(messageObject.na);
}
}
});
deferred.promise.then(function (response) {
$scope.transactionData = {
transactions: kpiService.totalArrayAmountWithRange(response.rows, 2, 0, response.rows.length / 2) + kpiService.totalArrayAmountWithRange(response.rows, 2, response.rows.length / 2 + 1, response.rows.length)
};
usSpinnerService.stop('loaderspin');
}, function(response) {
usSpinnerService.stop('loaderspin');
$scope.transactionData = {
transactions: response.na.msg
};
});
};
})();
/* calling the function */
persistentPromise(promiseFunction, someMessageObject);
答案 0 :(得分:3)
您可以将该代码完全分解为可重用的部分。请记住,promises使用return
语句并抽象异步值的基础。
Promise代表值而不是操作 - 你的dataFn不是一个函数,而是一个函数的结果,你只是在等待n
次10秒并且实际上不再执行调用
让我们从retry
开始:
// fn - arbitrary function that returns a promise, in your case this is what
// generates dataFn and __not__ dataFn itself. n - the number of retries
function retry(fn, n){
var reasons = []; // to keep rejection reasons
return $q.when().then(function retry(){ // start the chain
return fn(). // call the function
catch(function(err){ // if it failed
reasons.push(err); // accumulate reasons for failure of fn()
if(n-- <= 0) return $q.reject(reasons); // no more retries
return retry(); // recursive call, note the return
});
});
}
现在你可以多次重试任何promise返回函数,这是一个可分解的位。
现在让我们再看看你的代码。通过在函数中包含$scope
和uiSpinner进行大量的比较。让我们看看那个微调器。
function spinUntil(fn){
uiSpinnerService.start("loaderspin"); // start spinning, here and not outside
return fn().finally(function(){ // after FN resolves
uiSpinnerService.stop("loaderspin");
});
}
这将使您的整个代码看起来像:
spinUntil(function(){
return retry(promiseReturningFunction, 5);
}).then(function(data){ // retries performed, spinner done
$scope.transactionData = data; // assign here, don't complect the scope and the fn.
// spinner and retries already done, $scope is not a concern of retry or spinUntil
});
答案 1 :(得分:-3)
我带了这个函数,即使函数返回一个promise,它也能很好地工作。返回也是一个承诺,因此可以轻松处理结果。
function (fn, params, n) {
var deferred = $q.defer();
(function retry() {
return fn(params).$promise
.then(function (response) {
deferred.resolve(response);
},
function (response) {
if (n <= 0) {
deferred.reject(response);
return;
}
n--;
$timeout(function () {
return retry();
}, 5000);
});
})();
return deferred.promise;
};