定义
重试技术是在发生故障或异常情况时,自动尝试重新执行操作的一种技术。常见于各种异常情况,例如网络故障、服务端错误、资源不足等。
在实际应用中,重试技术通常需要设置一些参数,例如重试次数、重试间隔时间等,以根据具体的应用场景进行配置,从而最大程度地提高应用程序的可靠性和性能
优势
- 提高程序的可靠性:当请求失败时,重试技术可以自动重新尝试请求,从而提高应用程序的可靠性。
- 提高用户体验:重试技术可以让用户增加获取所需数据的成功率,提高用户的满意度。
案例
Axios-retry
Axios的retry
和retryDelay
是通过使用axios-retry这个库来实现的。这个库会在Axios的请求拦截器中注册一个retry
拦截器,并且在请求失败时触发拦截器的逻辑来进行重试。
// 源码
export default function axiosRetry(axios, defaultOptions) {
...
axios.interceptors.response.use(null, async (error) => {
const { config } = error;
// If we have no information to retry the request
if (!config) {
return Promise.reject(error);
}
const {
retries = 3,
retryCondition = isNetworkOrIdempotentRequestError,
retryDelay = noDelay,
shouldResetTimeout = false,
onRetry = () => {}
} = getRequestOptions(config, defaultOptions);
const currentState = getCurrentState(config);
//
if (await shouldRetry(retries, retryCondition, currentState, error)) {
// 记录重试次数
currentState.retryCount += 1;
const delay = retryDelay(currentState.retryCount, error);
...
// 发起重试
return new Promise((resolve) => setTimeout(() => resolve(axios(config)), delay));
}
return Promise.reject(error);
});
}
Retry
retry
是一个轻量级的、纯JavaScript实现的重试工具。
针对重试又封装好了很多技术细节,例如自定义重试次数
、重试间隔时间
和重试条件
。
// 源码
RetryOperation.prototype.attempt = function(fn, timeoutOps) {
this._fn = fn;
// 支持最大重试的时间
if (timeoutOps) {
if (timeoutOps.timeout) {
this._operationTimeout = timeoutOps.timeout;
}
if (timeoutOps.cb) {
this._operationTimeoutCb = timeoutOps.cb;
}
}
var self = this;
if (this._operationTimeoutCb) {
this._timeout = setTimeout(function() {
self._operationTimeoutCb();
}, self._operationTimeout);
}
this._operationStart = new Date().getTime();
// 重试
this._fn(this._attempts);
};
...
示例
下面以 oss上传文件
为例的 DEMO。
有些重试使用的是递归的方式,这里借助 for 循环
和 Promise
,实现重试功能。
const OSS = require('ali-oss');
const client = new OSS({
region: 'your-region',
accessKeyId: 'your-accessKeyId',
accessKeySecret: 'your-accessKeySecret',
bucket: 'your-bucket',
});
async function uploadWithRetry(filePath, options = {}) {
const defaultOptions = {
retries: 3,
retryDelay: 5000,
};
options = { ...defaultOptions, ...options };
for (let i = 0; i < options.retries; i++) {
try {
const result = await client.put(path.basename(filePath), filePath);
return result;
} catch (error) {
await new Promise(resolve => setTimeout(resolve, options.retryDelay));
}
}
throw new Error(`Failed to upload file after ${options.retries} retries.`);
}
uploadWithRetry('/path/to/file.txt')
.catch(error => console.log('Error:', error));
总结
重试
是一种在多种场景下提高程序可靠性
和鲁棒性
的技术手段,其包括减少请求失败率
、提高程序的稳定性
和可靠性
等优势。