思路
- 生成器函数:定义多个生成器函数,每个函数负责处理一个网络请求及其重试逻辑。
- 嵌套调用:通过在生成器函数内部
yield
另一个生成器函数来实现嵌套调用,确保请求之间的依赖关系。
- 异步操作:使用
fetch
进行网络请求,将其包装成返回Promise的函数以便在生成器中使用。
- 重试机制:在每个生成器函数中实现重试逻辑,如果请求失败则按照设定的次数进行重试。
代码实现
function fetchWithRetry(url, options = {}, maxRetries = 3, retryDelay = 1000) {
let retries = 0;
return new Promise((resolve, reject) => {
function attempt() {
fetch(url, options)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
resolve(response);
})
.catch(error => {
retries++;
if (retries <= maxRetries) {
setTimeout(attempt, retryDelay * retries);
} else {
reject(error);
}
});
}
attempt();
});
}
function* req1() {
try {
const response = yield fetchWithRetry('url1');
return response.json();
} catch (error) {
console.error('req1 failed:', error);
throw error;
}
}
function* req2(dataFromReq1) {
try {
const response = yield fetchWithRetry('url2', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataFromReq1)
});
return response.json();
} catch (error) {
console.error('req2 failed:', error);
throw error;
}
}
function* req3(dataFromReq2) {
try {
const response = yield fetchWithRetry('url3', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataFromReq2)
});
return response.json();
} catch (error) {
console.error('req3 failed:', error);
throw error;
}
}
function runGenerator(generator) {
const gen = generator();
function handleResult(result) {
if (result.done) {
return result.value;
}
return Promise.resolve(result.value)
.then(data => handleResult(gen.next(data)))
.catch(error => handleResult(gen.throw(error)));
}
return handleResult(gen.next());
}
runGenerator(function* () {
const data1 = yield* req1();
const data2 = yield* req2(data1);
const data3 = yield* req3(data2);
console.log('Final result:', data3);
})
.catch(error => console.error('Overall process failed:', error));
解释
fetchWithRetry
函数:封装了fetch
请求,并添加了重试逻辑。它接受URL、请求选项、最大重试次数和重试延迟作为参数。
req1
、req2
、req3
生成器函数:每个函数负责处理一个网络请求,使用yield
暂停执行并等待fetchWithRetry
返回结果。如果请求失败,会捕获错误并重新抛出。
runGenerator
函数:用于运行生成器,处理生成器的next
和throw
操作,通过递归调用handleResult
来处理生成器的嵌套调用。
- 最后部分:通过
runGenerator
运行一个主生成器,该生成器按顺序调用req1
、req2
、req3
,并处理最终结果或错误。