AngularJS 承诺重试
AngularJS Promise retries
我在使用重试功能时遇到了一些问题,希望得到一些帮助。我有一个我想调用的 $resource,直到出现成功条件或超过最大重试次数。
我似乎 运行 遇到的问题是,在我的重试函数中,我正在调用另一个承诺,这就是检查条件的地方。通过删除添加的承诺并在重试几次后创建默认成功条件,我可以使代码按预期运行,但我无法弄清楚如何正确地将新的承诺调用添加到函数中。
resource
是 Angular $resource 的替代品,returns $promise
我的代码如下:
resource.$promise.then(function (response) {
return keepTrying(state, 5);
}).then(function (response) {
}).catch(function (err) {
console.log(err);
});
以及 keepTrying 函数:
function keepTrying(state, maxRetries, deferred) {
deferred = deferred || $q.defer();
resource.$promise.then(function (response) {
success = response;
});
if (success) {
return deferred.resolve(success);
} else if (maxRetries > 0) {
setTimeout(function () {
keepTrying(state, maxRetries - 1, deferred);
}, 1000);
} else if (maxRetries === 0) {
deferred.reject('Maximum retries exceeded');
}
return deferred.promise;
}
您可以实现一个 retryOperation 函数,该函数 returns 一个新的错误承诺,直到作为参数传递的最大重试次数:
function retryOperation(retryCount) {
var count = 0;
function success(result) {
return result;
}
function error(result) {
++count;
if (count <= retryCount)
return $resource(...).query().$promise.then(success, error);
throw 'max retries reached';
}
return $resource(...).query().$promise.then(success, error);
}
用法
retryOperation(3).then(
function success(result) {
// done!
},
function error(reason) {
alert(reason);
});
var app = angular.module('app', []);
app.controller('ctrl', function($q) {
function retryOperation(count) {
var retryCount = 0;
function operation() {
var deferred = $q.defer();
deferred.reject('failed');
return deferred.promise;
}
function success(result) {
return result;
}
function error(result) {
++retryCount;
if (retryCount <= count) {
alert('retrying ' + retryCount);
return operation().then(success, error);
}
throw 'maximum retries reached';
}
return operation().then(success, error);
}
retryOperation(3).then(
function success(result) {
alert('done');
},
function error(result) {
alert(result);
});
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="ctrl">
<input type="text" ng-model="name" />{{name}}
</body>
</html>
您尝试的问题是您没有重新查询资源,而是一遍又一遍地使用对已查询资源的承诺。
您需要做的是使用一个函数,该函数将 (a) 启动查询,以及 (b) return 对启动的查询的承诺。像这样:
function () { return $resource.get().$promise; }
然后你可以把它传递给这样的东西,它会重试。
function retryAction(action, numTries) {
return $q.when()
.then(action)
.catch(function (error) {
if (numTries <= 0) {
throw error;
}
return retryAction(action, numTries - 1);
});
}
以下是开始的方式:
retryAction(function () { return $resource.get().$promise; }, 5)
.then(function (result) {
// do something with result
});
这种方法的一个好处是,即使您传递给它的函数在调用它时抛出错误,或者根本没有 return 承诺,重试功能和 return通过已解决的承诺获得结果仍然有效。
我在使用重试功能时遇到了一些问题,希望得到一些帮助。我有一个我想调用的 $resource,直到出现成功条件或超过最大重试次数。
我似乎 运行 遇到的问题是,在我的重试函数中,我正在调用另一个承诺,这就是检查条件的地方。通过删除添加的承诺并在重试几次后创建默认成功条件,我可以使代码按预期运行,但我无法弄清楚如何正确地将新的承诺调用添加到函数中。
resource
是 Angular $resource 的替代品,returns $promise
我的代码如下:
resource.$promise.then(function (response) {
return keepTrying(state, 5);
}).then(function (response) {
}).catch(function (err) {
console.log(err);
});
以及 keepTrying 函数:
function keepTrying(state, maxRetries, deferred) {
deferred = deferred || $q.defer();
resource.$promise.then(function (response) {
success = response;
});
if (success) {
return deferred.resolve(success);
} else if (maxRetries > 0) {
setTimeout(function () {
keepTrying(state, maxRetries - 1, deferred);
}, 1000);
} else if (maxRetries === 0) {
deferred.reject('Maximum retries exceeded');
}
return deferred.promise;
}
您可以实现一个 retryOperation 函数,该函数 returns 一个新的错误承诺,直到作为参数传递的最大重试次数:
function retryOperation(retryCount) {
var count = 0;
function success(result) {
return result;
}
function error(result) {
++count;
if (count <= retryCount)
return $resource(...).query().$promise.then(success, error);
throw 'max retries reached';
}
return $resource(...).query().$promise.then(success, error);
}
用法
retryOperation(3).then(
function success(result) {
// done!
},
function error(reason) {
alert(reason);
});
var app = angular.module('app', []);
app.controller('ctrl', function($q) {
function retryOperation(count) {
var retryCount = 0;
function operation() {
var deferred = $q.defer();
deferred.reject('failed');
return deferred.promise;
}
function success(result) {
return result;
}
function error(result) {
++retryCount;
if (retryCount <= count) {
alert('retrying ' + retryCount);
return operation().then(success, error);
}
throw 'maximum retries reached';
}
return operation().then(success, error);
}
retryOperation(3).then(
function success(result) {
alert('done');
},
function error(result) {
alert(result);
});
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="ctrl">
<input type="text" ng-model="name" />{{name}}
</body>
</html>
您尝试的问题是您没有重新查询资源,而是一遍又一遍地使用对已查询资源的承诺。
您需要做的是使用一个函数,该函数将 (a) 启动查询,以及 (b) return 对启动的查询的承诺。像这样:
function () { return $resource.get().$promise; }
然后你可以把它传递给这样的东西,它会重试。
function retryAction(action, numTries) {
return $q.when()
.then(action)
.catch(function (error) {
if (numTries <= 0) {
throw error;
}
return retryAction(action, numTries - 1);
});
}
以下是开始的方式:
retryAction(function () { return $resource.get().$promise; }, 5)
.then(function (result) {
// do something with result
});
这种方法的一个好处是,即使您传递给它的函数在调用它时抛出错误,或者根本没有 return 承诺,重试功能和 return通过已解决的承诺获得结果仍然有效。