十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

fetch:超时、重试与 AbortController

fetch:超时、重试与 AbortController fetch是浏览器里发 HTTP 请求的标准方法。默认它不会因「等太久」自动失败也不会帮你重试。线上接口偶发超时、网关 503、限流 429若页面一直转圈或疯狂连打体验与服务都会受伤。下面把三件事拆开超时怎么取消、什么错误值得重试、怎么和 AbortController 配合。一、先说一个具体麻烦你写了constresawaitfetch(/api/report)constdataawaitres.json()上面代码中没有超时。服务端卡住时Promise 可能一直 pending按钮转个不停。用户重复点击又发出第二、第三次请求。需要两样能力1到点取消2区分「可重试」与「不该重试」避免把 400 校验错误也重打三遍二、AbortController取消的总闸AbortController提供一个signal。把它传给fetch调用abort()即可取消。constacnewAbortController()fetch(/api/report,{signal:ac.signal})// 某处ac.abort()上面代码中取消后fetch会以 AbortError 一类错误拒绝具体名称因环境略有差异。同一signal也可传给多个关联请求一并取消。超时只是「到时间自动 abort」的一种用法。三、最小超时封装思路A创建 controllerBsetTimeout到点 abortCfinally里清定时器。exportasyncfunctionfetchWithTimeout(url,options{},ms8000){constacnewAbortController()consttimersetTimeout(()ac.abort(),ms)try{returnawaitfetch(url,{...options,signal:ac.signal})}finally{clearTimeout(timer)}}上面代码中若调用方自己也传了signal生产代码还应把外部 abort 与超时 abort 合并例如AbortSignal.any或手动监听转发。入门先掌握「超时 定时 abort」。用户离开页面或关闭弹窗时同样应 abort避免无用请求占着连接与回调。四、什么错误才重试不是所有失败都该重试。通常更值得重试1网络断开、DNS 临时失败2408/429/502/503/5043你明确标成幂等的 GET / 某些可安全重放的写操作需业务保证通常不要盲着重试1400/401/403/404/422改请求或鉴权不是再打一次2非幂等 POST 已可能成功但响应丢失——重试可能造成重复下单需幂等键五、退避重试的最小形状「立刻再打」容易把服务打崩。常见做法是指数退避1s、2s、4s……并加一点抖动。asyncfunctionfetchWithRetry(url,options,{retries2,baseMs400}{}){letlastErrfor(leti0;iretries;i){try{constresawaitfetchWithTimeout(url,options,8000)if(res.ok)returnresif(![429,502,503,504].includes(res.status)||iretries)returnres}catch(err){lastErrerrif(iretries)throwerr}constwaitbaseMs*2**iMath.random()*100awaitnewPromise((r)setTimeout(r,wait))}throwlastErr}上面代码中逻辑是示意成功或不可重试状态码就返回可重试则等待后再来。真实项目还应1尊重Retry-After2把超时 abort 与「主动取消」区分开——用户取消不应再重试3对写操作加幂等键或禁止自动重试六、和 UI 状态机对齐请求层做好了还要和界面约定1进行中禁用提交或显示 loading2取消abort并忽略随后的过期响应3失败按状态码给文案401 去登录429 提示稍后再试竞态常见坑先发的慢请求后返回覆盖了新数据。用递增的 request id或每次新请求 abort 旧请求可以避免。七、常见误区1只await fetch不看res.okHTTP 404 不会进 catch需要自己判断。2所有方法统一重试三次非幂等写操作很危险。3超时时间设得极短又极多重试等于自己制造雪崩。4catch 到 AbortError 还弹「网络错误」用户主动取消应静默处理。5忘记清 timer组件卸载后仍 abort或 timer 泄漏。八、小结fetch本身不管超时与重试。用 AbortController 做取消用定时 abort 做超时用状态码与幂等性决定是否退避重试。三件事分开设计再组合混在一个「万能 request」里最容易变成黑盒。完
返回列表