实现代码
function asyncRequestWithRetry(url, retries = 3, delay = 1000) {
return new Promise((resolve, reject) => {
let attempt = 0;
const makeRequest = () => {
// 模拟异步请求
setTimeout(() => {
const shouldFail = Math.random() < 0.5; // 模拟50%失败率
if (shouldFail && attempt < retries) {
attempt++;
setTimeout(makeRequest, delay);
} else if (shouldFail && attempt >= retries) {
reject(new Error(`Request to ${url} failed after ${retries} attempts`));
} else {
resolve({ data: `Response from ${url}` });
}
}, 1000);
};
makeRequest();
});
}
function* requestGenerator() {
const initialUrl = 'https://example.com/initial';
try {
let response = yield asyncRequestWithRetry(initialUrl);
yield* iterateRequests(response.data, 5);
} catch (error) {
console.error('Initial request failed:', error);
}
}
function* iterateRequests(data, count) {
for (let i = 1; i <= count; i++) {
const url = `https://example.com/${i}?param=${data}`;
try {
let response = yield asyncRequestWithRetry(url);
console.log(`Request ${i} success:`, response);
} catch (error) {
console.error(`Request ${i} failed:`, error);
}
}
}
function runGenerator(generator) {
const iterator = generator();
function handleResult(result) {
if (result.done) {
return;
}
result.value.then((response) => {
handleResult(iterator.next(response));
}).catch((error) => {
console.error('Error in request:', error);
handleResult(iterator.throw(error));
});
}
handleResult(iterator.next());
}
runGenerator(requestGenerator);
实现思路
- 异步请求带重试机制:
asyncRequestWithRetry
函数创建一个Promise来模拟异步请求。它接受URL、最大重试次数retries
和重试延迟时间delay
作为参数。在每次请求失败且重试次数未达到上限时,它会延迟一段时间后重新发起请求。当达到最大重试次数仍失败时,Promise被拒绝。
- 生成器函数:
requestGenerator
是主生成器函数,它发起第一个请求并处理可能的错误。然后,它通过yield*
委托给iterateRequests
生成器函数。
iterateRequests
生成器函数负责依次发起后续请求,每个请求的URL依赖于上一个请求的返回数据。在每次请求成功或失败时,都会进行相应的日志记录。
- 运行生成器:
runGenerator
函数用于运行生成器。它通过迭代生成器并处理每个yield
返回的Promise来实现依次执行异步请求。如果Promise被拒绝,错误会被捕获并通过iterator.throw(error)
传递给生成器内部进行处理。