装企网站建设长春 网络设计

张小明 2025/12/27 20:50:01
装企网站建设,长春 网络设计,天元建设集团有限公司济南第六建筑分公司,公司企业网站推广前端新人必学#xff1a;手把手封装 fetch#xff0c;告别重复请求代码#xff08;附实战技巧#xff09;前端新人必学#xff1a;手把手封装 fetch#xff0c;告别重复请求代码#xff08;附实战技巧#xff09;为什么每次写接口都要复制粘贴#xff1f;看看你项目里…前端新人必学手把手封装 fetch告别重复请求代码附实战技巧前端新人必学手把手封装 fetch告别重复请求代码附实战技巧为什么每次写接口都要复制粘贴看看你项目里是不是一堆重复的 fetch 逻辑fetch 是什么又不是什么从零开始封装一个实用的 fetch 工具1. 统一配置2. 序列化 QueryString3. 核心函数 request4. 工具函数5. 顺手导出 get/post 等快捷方法让错误处理不再头疼拦截器机制怎么加进去支持取消请求和防重发自动重试与降级策略开发调试神器请求日志与 Mock 支持真实项目中的封装姿势1. 与 TypeScript 甜蜜双排2. 环境变量与多基址3. 模块拆分遇到“请求发不出去”怎么办进阶技巧缓存策略与性能优化别再裸奔了给你的 fetch 加点“盔甲”封装完别急着提交先测一测你以为封装完了其实才刚开始前端新人必学手把手封装 fetch告别重复请求代码附实战技巧警告本文会让你的fetch代码从“能跑”进化到“能炫”请自备咖啡和键盘阅读过程中若忍不住ctrlc/ctrlv作者概不负责。为什么每次写接口都要复制粘贴看看你项目里是不是一堆重复的 fetch 逻辑先别急着否认打开你最近的services文件夹大概率能看到这样的“奇观”// user.jsexportfunctiongetUser(id){returnfetch(/api/user/${id},{headers:{Content-Type:application/json,Authorization:Bearer${localStorage.token}}}).then(resres.json())}// order.jsexportfunctiongetOrder(id){returnfetch(/api/order/${id},{headers:{Content-Type:application/json,Authorization:Bearer${localStorage.token}}}).then(resres.json())}这两段代码像失散多年的双胞胎除了 URL 不一样其他连空格都懒得换。需求一改——“超时时间改成 8 秒”、“错误码 401 要跳登录”、“所有请求加个Request-ID”——你就得全局搜索替换一不小心就把同事的代码给“误杀”。痛定思痛咱们来造一个“万能胶”一次封装终身受用后续只写业务不写废话。fetch 是什么又不是什么把fetch当成“原生提供的快递小哥”✅ 免费、浏览器自带、支持 Promise、基于标准❌ 不会自动带 cookie默认same-origin、不会自动序列化对象、不会默认超时、不会自动根据状态码抛异常、不支持请求进度监控、不支持 Node18 以前而 axios 像“顺丰”包装好、功能全、拦截器、超时、自动 JSON、错误处理一条龙但体积 13 kBgzip 后约。XMLHttpRequest 则是“邮政包裹”老派、啰嗦、回调地狱现在基本退居二线。结论“小哥”虽然青涩但胜在轻量、可控、可塑性强自己给它配辆电动车封装一层就能媲美顺丰还不用给快递费。从零开始封装一个实用的 fetch 工具先搭骨架再填血肉。我们起名request.js放在src/utils下日后所有接口都靠它刷脸。1. 统一配置constDEFAULT_CONFIG{baseURL:,timeout:6000,headers:{Content-Type:application/json}}2. 序列化 QueryStringfunctionqsStringify(obj){returnnewURLSearchParams(obj).toString()}3. 核心函数requestasyncfunctionrequest(url,options{}){// 1. 合并配置constconfigmergeConfig(DEFAULT_CONFIG,options)// 2. 拼接 baseURLurlconfig.baseURLurl// 3. 处理 paramsif(config.params){constsepurl.includes(?)?:?urlsepqsStringify(config.params)}// 4. 超时处理constcontrollernewAbortController()consttimersetTimeout(()controller.abort(),config.timeout)// 5. 自动 JSON 化if(config.datatypeofconfig.dataobject){config.bodyJSON.stringify(config.data)}try{constresponseawaitfetch(url,{...config,signal:controller.signal})clearTimeout(timer)// 6. 自动反序列化constcontentTyperesponse.headers.get(Content-Type)||letdataif(contentType.includes(application/json)){dataawaitresponse.json()}else{dataawaitresponse.text()}// 7. 状态码校验if(!response.ok){returnPromise.reject(createError(response.status,data))}returndata}catch(err){clearTimeout(timer)// 网络错误 / 超时thrownormalizeNetworkError(err)}}4. 工具函数functionmergeConfig(def,opt){return{...def,...opt,headers:{...def.headers,...opt.headers}}}functioncreateError(code,data){consterrnewError(Request failed with status${code})err.codecode err.datadatareturnerr}functionnormalizeNetworkError(err){if(err.nameAbortError){err.messageRequest timeout}returnerr}5. 顺手导出 get/post 等快捷方法exportconstget(url,params,opts)request(url,{...opts,method:GET,params})exportconstpost(url,data,opts)request(url,{...opts,method:POST,data})exportdefaultrequest一行import { get, post } from /utils/request就能到处浪。让错误处理不再头疼后端返回格式千奇百怪{ code: 500, msg: 服务器冒烟了 }{ error: { detail: 参数不对 } }{ status: fail, reason: 余额不足 }前端如果每个接口都if (res.code ! 200) alert(res.msg)迟早精神分裂。统一“翻译器”安排上functiontransformError(data){// 优先取常用字段returndata?.msg||data?.message||data?.error?.detail||系统繁忙}在request里一旦捕获异常就交给全局提示import{toast}fromreact-hot-toast// 或 antd/element-plusrequest.interceptors{response:[asyncresres,err{constmsgtransformError(err.data)||err.message toast.error(msg)returnPromise.reject(err)}]}小贴士把提示函数作为参数注入避免工具层依赖 UI 库测试时也能静默处理。拦截器机制怎么加进去fetch原生没有拦截器但我们可以“外包”一层数组循环执行classRequest{constructor(config){this.configconfigthis.interceptors{request:[],response:[]}}asyncrun(url,options){// 请求拦截for(constfnofthis.interceptors.request){({url,options}awaitfn({url,options})||{url,options})}letresponsetry{responseawaitfetch(url,options)}catch(e){// 网络层错误response{ok:false,status:0,statusText:e.message}}// 响应拦截for(constfnofthis.interceptors.response){responseawaitfn(response)||response}returnresponse}}自动带 token 的场景request.interceptors.request.push(({url,options}){consttokenlocalStorage.getItem(token)if(token){options.headersoptions.headers||{}options.headers[Authorization]Bearer${token}}return{url,options}})日志上报request.interceptors.response.push(asyncres{if(!res.ok){report({url:res.url,status:res.status,timestamp:Date.now()})}returnres})支持取消请求和防重发用户狂点“提交”按钮后端收到 5 次同款订单老板连夜买站票跑路。利用AbortController做“上一次没回来就取消”constpendingMapnewMap()functiongenKey(url,method,data){return[url,method,JSON.stringify(data)].join()}functioncancelRepeat(config){constkeygenKey(config.url,config.method,config.data)if(pendingMap.has(key)){pendingMap.get(key).abort()}constcontrollernewAbortController()pendingMap.set(key,controller)config.signalcontroller.signal}// 响应后删除functionremovePending(config){constkeygenKey(config.url,config.method,config.data)pendingMap.delete(key)}在拦截器里调用即可。进阶对非幂等请求POST/PUT/PATCH才做取消GET 请求保留缓存即可。自动重试与降级策略网络抖动 502立刻抛错太绝情。给关键接口 3 次机会asyncfunctionrequestWithRetry(url,options,retry3){for(leti0;iretry;i){try{returnawaitrequest(url,options)}catch(e){constisLastiretry-1if(isLast||e.code400)throwe// 业务错误不重试awaitsleep(Math.pow(2,i)*1000)// 指数退避}}}functionsleep(ms){returnnewPromise(rsetTimeout(r,ms))}降级如果连续失败返回本地兜底数据让页面不至于空白const降级数据require(/mock/fallback.json)try{returnawaitrequestWithRetry(/api/critical)}catch{return降级数据}开发调试神器请求日志与 Mock 支持本地想看“发出去的是什么妖魔鬼怪”一行拦截器搞定if(process.env.NODE_ENVdevelopment){request.interceptors.request.push(({url,options}){console.groupCollapsed([${options.method}]${url})console.log(headers:,options.headers)console.log(body:,options.body)console.groupEnd()return{url,options}})}Mock 数据用vite-plugin-mock或msw都行这里给个极简内存版constmockRoutes{GET /api/user:{id:1,name:纸糊小能手}}request.interceptors.request.push(({url,options}){constkey${options.method}${url}if(mockRoutes[key]){returnPromise.resolve(mockRoutes[key])}return{url,options}})注意如果返回的是 Promise会短路真实请求直接作为响应。真实项目中的封装姿势1. 与 TypeScript 甜蜜双排interfaceBaseResponseTany{code:numberdata:Tmsg?:string}exportasyncfunctiongetTany(url:string,params?:object):PromiseT{constresawaitrequest(url,{method:GET,params})return(resasBaseResponseT).data}调用时享受类型推导interfaceUser{id:number;name:string}constuserawaitgetUser(/api/user)// user 自动提示 name 属性2. 环境变量与多基址.env文件VITE_API_BASEhttps://api.example.com VITE_API_BASE_DEVhttp://localhost:3001constbaseURLimport.meta.env.DEV?import.meta.env.VITE_API_BASE_DEV:import.meta.env.VITE_API_BASE3. 模块拆分src/ api/ index.ts // 导出 request 实例 modules/ user.ts order.tsuser.ts只写业务importrequestfrom../indexexportconstgetUser(id:number)request.get(/user/${id})遇到“请求发不出去”怎么办CORS浏览器报错No Access-Control-Allow-Origin时先确认后端Access-Control-Allow-Headers是否包含自定义头如Authorization。本地开发用 vite 代理// vite.config.jsserver:{proxy:{/api:{target:http://localhost:3001,changeOrigin:true}}}HTTPS 混合内容页面https却请求http浏览器直接拦截。把后端也上证书或者前端统一走/api代理。证书无效本地自签证书不被信任chrome 地址栏输入thisisunsafe先跳过或者把.crt加入系统受信任根证书。进阶技巧缓存策略与性能优化GET 请求在内存里缓存 5 分钟减少“抖动刷新”constcachenewMap()functionwithCache(fn,ttl5*60*1000){returnasync(...args){constkeyJSON.stringify(args)if(cache.has(key)){const{data,expiry}cache.get(key)if(Date.now()expiry)returndata}constresultawaitfn(...args)cache.set(key,{data:result,expiry:Date.now()ttl})returnresult}}exportconstgetUserCachewithCache(getUser)配合 React 的useSWRimportuseSWRfromswrconst{data}useSWR(/api/user,getUserCache)秒杀“重复请求地狱”。别再裸奔了给你的 fetch 加点“盔甲”敏感信息过滤上报日志时把手机号、身份证replace成*。XSS 注入任何拼接在 URL 上的参数都要encodeURIComponent别给坏人留?redirectscript的口子。CSRF同源接口如果依赖 cookie一定让后端开启SameSiteStrict或者加自定义头X-Requested-With: fetch后端校验缺失则拒绝。封装完别急着提交先测一测单元测试用JestmswMock Service Worker// request.test.tsimport{rest}frommswimport{setupServer}frommsw/nodeimportrequestfrom../src/utils/requestconstserversetupServer(rest.get(/api/test,(req,res,ctx){returnres(ctx.json({hello:world}))}))beforeAll(()server.listen())afterAll(()server.close())test(should return json,async(){constdataawaitrequest(/api/test)expect(data).toEqual({hello:world})})跑完npm run test:ci全绿再git push否则半夜被测试姐姐 别怪我没提醒。你以为封装完了其实才刚开始项目像养娃接口会越来越多需求会越来越骚“我要 GraphQL” “我要批量请求” “我要插件化自由插拔”把核心拆成“中间件”模式参考koa-composeclassCore{use(fn){this.middlewares.push(fn)returnthis}exec(context){constdispatchi{constfnthis.middlewares[i]if(!fn)returnreturnfn(context,()dispatch(i1))}returndispatch(0)}}链式调用request.use(cache).use(retry).use(logger)每新增能力就是一条中间件而不用回炉重造。最后记住一句话“好的封装不是让你少写代码而是让你把精力花在更值得折腾的地方——比如给产品小姐姐调像素。”祝你与fetch白头偕老永无502。欢迎来到我的博客很高兴能够在这里和您见面希望您在这里可以感受到一份轻松愉快的氛围不仅可以获得有趣的内容和知识也可以畅所欲言、分享您的想法和见解。推荐DTcode7的博客首页。一个做过前端开发的产品经理经历过睿智产品的折磨导致脱发之后励志要翻身农奴把歌唱一边打入敌人内部一边持续提升自己为我们广大开发同胞谋福祉坚决抵制睿智产品折磨我们码农兄弟专栏系列点击解锁学习路线(点击解锁知识定位《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架记录请求、封装、tabbar、UI组件的学习记录和使用技巧等《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容入坑前端或者辅助学习的必看知识《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客共同构建用户界面。通过操作DOM元素、响应事件、发起网络请求等JS使页面能够响应用户行为实现数据动态展示和页面流畅跳转是现代Web开发的核心《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法同时收集精美的CSS效果代码用来丰富你的web网页《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素通过JavaScript及其提供的绘图API开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力使得前端绘图技术更加丰富和多样化《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅《python相关博客》持续更新中~Python简洁易学的编程语言强大到足以应对各种应用场景是编程新手的理想选择也是专业人士的得力工具《sql数据库相关博客》持续更新中~SQL数据库高效管理数据的利器学会SQL轻松驾驭结构化数据解锁数据分析与挖掘的无限可能《算法系列相关博客》持续更新中~算法与数据结构学习总结通过JS来编写处理复杂有趣的算法问题提升你的技术思维《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术涉及软件开发、网络建设、系统维护等领域的知识《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理只要是从事信息化相关行业的人员都应该掌握这些信息化的基础知识可以不精通但是一定要了解避免日常工作中贻笑大方《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧提升自我能力与面试通过率扩展知识面《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等《photoshop相关博客》持续更新中~基础的PS学习记录含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结日常开发办公生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具丰富阅历给大家提供处理事情的更多角度学习了解更多的便利工具如Fiddler抓包、办公快捷键、虚拟机VMware等工具吾辈才疏学浅摹写之作恐有瑕疵。望诸君海涵赐教。望轻喷嘤嘤嘤非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益纵其简陋未及渊博亦足以略尽绵薄之力。倘若尚存阙漏敬请不吝斧正俾便精进
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

快速的宝安网站建设深圳企业招聘

常用组件 文本组件(Text) Text是显示文本的基础组件之一 Text定义介绍 interface TextInterface{(content?: string | Resource):TextAttributes; }content:要显示的文本内容,一个简单的例子如下: Text(Hello&#xf…

张小明 2025/12/26 0:43:30 网站建设

建设企业网站的流程网站的关键词排名怎么做

MusicFree插件系统是这款开源播放器的核心扩展机制,通过灵活的插件架构,让用户能够突破基础播放限制,打造完全个性化的音乐体验环境。无论你是追求高品质音源的发烧友,还是希望聚合多个平台资源的实用主义者,这套插件生…

张小明 2025/12/25 19:31:52 网站建设

新闻热点事件2023最新phpcms v9网站性能优化

应用程序配置与部署全流程指南 在应用程序的部署与管理中,合理配置应用程序、明确部署类型的要求以及采用有效的检测方法至关重要。以下将详细介绍这些方面的内容,并以 Paint.NET 应用程序为例进行说明。 部署类型与要求 部署类型类似于基本的防火墙规则。防火墙会首先根据…

张小明 2025/12/25 16:34:30 网站建设

常州网站建设建设网站好公司

5分钟掌握JSLint:JavaScript代码质量检查的终极指南 【免费下载链接】jslint JSLint, The JavaScript Code Quality and Coverage Tool 项目地址: https://gitcode.com/gh_mirrors/js/jslint JSLint是一款强大的JavaScript代码质量工具,能够帮助开…

张小明 2025/12/25 16:28:23 网站建设

网站优化主旨建筑设计集团

稀土因独特物理化学特性,成为尖端科技与国防领域的关键材料,国际稀土贸易的发展既受产业技术变革驱动,也受大国战略博弈影响,而对其展开研究,无论是对各国产业发展还是全球产业链稳定都意义重大 参考周晓阳、徐衍爽等…

张小明 2025/12/27 18:54:10 网站建设

郴州建设网站企业文化墙

NetSend:终极内网文件传输完整指南,简单快速免费使用 【免费下载链接】netSend 内网传输工具 项目地址: https://gitcode.com/gh_mirrors/ne/netSend 还在为局域网内设备间的文件传输而烦恼吗?想象一下,无需数据线、不依赖…

张小明 2025/12/26 6:05:12 网站建设