函数抽象&promise函数作为参数
Function abstraction & promise function as a parameter
我正在尝试抽象下面的函数,以便我可以轻松地重用。函数基本上运行一个给定的函数,该函数 returns 承诺最多 5 次或直到承诺得到解决。
DataFn 让我特别难过。它 returns 一个承诺,但是当运行函数在第一次失败后第二次执行时,它不会再次尝试连接到服务器。如果我对函数名称进行硬编码,它会起作用,但作为传递的参数仅在开始时起作用。
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);
您可以将该代码完全分解为可重用的部分。请记住,承诺使用 return
语句并抽象出异步值的基础。
Promises 表示值而不是操作 - 您的 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
});
我附带了这个函数,即使函数 returns 是一个承诺,它也能很好地工作。 Return 也是一个承诺,因此可以轻松处理结果。
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;
};
我正在尝试抽象下面的函数,以便我可以轻松地重用。函数基本上运行一个给定的函数,该函数 returns 承诺最多 5 次或直到承诺得到解决。 DataFn 让我特别难过。它 returns 一个承诺,但是当运行函数在第一次失败后第二次执行时,它不会再次尝试连接到服务器。如果我对函数名称进行硬编码,它会起作用,但作为传递的参数仅在开始时起作用。
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);
您可以将该代码完全分解为可重用的部分。请记住,承诺使用 return
语句并抽象出异步值的基础。
Promises 表示值而不是操作 - 您的 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
});
我附带了这个函数,即使函数 returns 是一个承诺,它也能很好地工作。 Return 也是一个承诺,因此可以轻松处理结果。
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;
};