用async函数实现无限循环拉取服务端数据,递归写法是否正确?
递归实现无限拉取数据的写法分析
你的代码可以实现无限循环拉取数据的需求,但存在几个需要注意的点:
现有代码的合理性
- 异步递归不会触发调用栈溢出:
infinityLoop通过Promise.then触发下一次调用,每次调用都在异步任务队列中执行,不会在当前调用栈中积累,因此不会出现栈溢出问题。 - 重试机制有效:
fetchData的递归重试逻辑能处理临时请求失败的场景,最多重试5次后才会抛出错误。
潜在问题
- 未处理最终失败的场景:如果
fetchData重试5次后仍失败,会抛出错误,但infinityLoop中没有对应的catch处理,未捕获的Promise拒绝会直接终止整个无限循环。 - 可读性较差:递归写法的无限循环不如同步循环直观,后续维护时不易快速理解逻辑。
优化后的写法
推荐改用async/await配合while(true)的写法,同时补充全局错误捕获,逻辑更清晰健壮:
function pause(delay) { return new Promise(r => setTimeout(r, delay)) } async function fetchData(url, tries = 5) { try { const response = await fetch(url); if (!response.ok) throw new Error('Request error'); const contentType = response.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) throw new TypeError('not a JSON') const jsonData = await response.json(); return jsonData; } catch(err) { console.error('catch error:', err, 'tries left', tries); if (tries === 0) throw err; await pause(1500); return fetchData(url, tries - 1); } } async function infinityLoop() { while (true) { try { const data = await fetchData('test.json'); console.log(data); } catch (err) { console.error('最终拉取失败,等待后重试:', err); } await pause(1000); } } infinityLoop();
优化点说明
- 用
while(true)替代递归,逻辑更直白,符合无限循环的直观认知。 - 给整个拉取流程加
try/catch,即使fetchData彻底失败,也会继续进入下一次循环,不会终止。 - 去掉错误重新包装的冗余代码,直接抛出原错误更简洁。
内容的提问来源于stack exchange,提问作者Bener Beer
相关产品推荐
相关产品推荐

