尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

09 Vue 3 接口请求与异步容错

09 Vue 3 接口请求与异步容错 Vue 3 接口请求与异步容错一、页面数据从哪里来真实 Vue 页面通常不会把全部数据写死在组件中而是从后端获取Vue 页面 ↓ 调用 API 封装函数 ↓ 发送 HTTP 后端服务 ↓ 返回 JSON Vue 更新 ref ↓ 模板和计算属性自动更新页面组件应关注“什么时候请求、如何保存结果、失败时如何展示”具体请求地址和 HTTP 配置通常封装到api目录。二、封装 API 函数importrequestfrom/utils/request;exportfunctiongetHeatDetail(heatId:string){returnrequest({url:/bof/heat/${heatId},method:get});}带查询参数exportfunctiongetHeatPlayback(heatId:string,params:{interval_seconds:number;signals:string;}){returnrequest({url:/bof/heat/${heatId}/playback,method:get,params});}页面中只调用const{data}awaitgetHeatDetail(heatId.value);三、async/awaitasyncfunctionloadHeatDetail(){constresponseawaitgetHeatDetail(heatId.value);heatMeta.valueresponse.data;}await会暂停当前异步函数等待 Promise 完成但不会阻塞整个浏览器线程。调用异步函数voidloadHeatDetail();或者awaitloadHeatDetail();是否等待取决于后续逻辑是否依赖结果。四、加载状态constloadingref(false);模板el-button :loadingloading clickloadData 刷新 /el-button main v-loadingloading 页面内容 /main函数asyncfunctionloadData(){loading.valuetrue;try{// 请求}finally{loading.valuefalse;}}将关闭 Loading 放在finally中能够保证成功和失败都执行。五、try/catch/finallyconsterrorMessageref();asyncfunctionloadData(){loading.valuetrue;errorMessage.value;try{const{data}awaitgetHeatDetail(heatId.value);heatMeta.valuedata;}catch(error:unknown){errorMessage.valuegetErrorMessage(error);}finally{loading.valuefalse;}}错误转换functiongetErrorMessage(error:unknown):string{if(errorinstanceofError){returnerror.message;}returnString(error);}六、首次加载与手动刷新复用同一函数onMounted((){voidloadData();});el-button clickloadData刷新/el-button这样首次加载和手动刷新不会出现两套重复逻辑。七、串行请求constdetailResultawaitgetHeatDetail(heatId.value);constplaybackResultawaitgetHeatPlayback(heatId.value);第二个请求必须等第一个完成。适合第二个请求依赖第一个结果需要明确执行顺序前一步失败后不应继续。如果两个接口相互独立串行会增加总等待时间。八、使用Promise.all()并行请求const[detailResult,playbackResult]awaitPromise.all([getHeatDetail(heatId.value),getHeatPlayback(heatId.value)]);两个请求同时发出总时间通常接近较慢请求的耗时。Promise.all()的特点任何一个 Promise 拒绝整个Promise.all()立即进入异常详情成功 回放失败 预测仍在请求 ↓ Promise.all 整体 rejected当所有数据都属于页面的必要条件时这种行为是合理的。九、使用Promise.allSettled()处理局部失败复杂大屏的各个区域可能相对独立炉次详情历史回放全流程预测线性回归预测。可以并行请求constresultsawaitPromise.allSettled([getHeatDetail(heatId.value),getHeatPlayback(heatId.value),predictFullProcess(heatId.value),predictLinearRegression(heatId.value)]);结果不会因为一个接口失败而整体抛出。判断状态const[detailResult,playbackResult]results;if(detailResult.statusfulfilled){heatMeta.valuedetailResult.value.data;}else{heatMeta.valuenull;setSectionError(详情接口失败);}if(playbackResult.statusfulfilled){playback.valueplaybackResult.value.data;}else{playback.valuenull;setSectionError(回放接口失败);}两种结果类型fulfilled → value rejected → reason十、局部容错的页面设计合理目标不是“任何失败都装作没发生”而是必要数据失败 → 阻断相关页面功能 可选数据失败 → 只降级对应区域 已有旧数据 → 必要时保留上一帧例如详情成功、回放成功、预测失败 ↓ 基础页面和回放正常显示 预测区域显示“模型服务不可达”这比整个页面白屏更符合监控系统需求。十一、错误应该分层页面级错误页面无法继续使用炉次不存在权限失败核心详情无法获取。区域级错误只有一个模块失败预测总线失败场数据失败控制状态失败。降级提示页面仍然可用但使用替代数据保留上一快照使用基础信号代替设备控制接口使用符号模型代替场数据使用历史预测结果。不同错误不应该全部写进同一个字符串否则一个区域的新错误可能覆盖另一个区域的重要提示。十二、保留上一帧实时请求失败时不一定要清空数据asyncfunctionloadSnapshot(){try{const{data}awaitgetSnapshot();snapshot.valuedata;snapshotError.value;}catch(error){snapshotError.value快照加载失败已保留上一帧。;if(!snapshot.value){showFatalError(error);}}}逻辑是已有数据 临时失败 → 保留旧数据并提示 首次请求就失败 → 显示更明显错误十三、不要在失败时无条件清空所有状态下面的做法可能让页面闪烁snapshot.valuenull;awaitloadSnapshot();更平滑的做法是保留旧值只有新请求成功后再替换。是否保留旧数据取决于业务旧数据必须同时显示时间戳或“数据已过期”提示避免被误认为实时结果。十四、请求门控与重复请求实时轮询可能在上一次请求未完成时再次触发。可以使用简单锁letsnapshotLoadingfalse;asyncfunctionloadSnapshot(){if(snapshotLoading){return;}snapshotLoadingtrue;try{const{data}awaitgetSnapshot();snapshot.valuedata;}finally{snapshotLoadingfalse;}}更复杂时可以为不同接口建立独立门控snapshot field-snapshot control-state避免一个接口的锁阻止其他独立接口。十五、请求竞争与过期结果用户快速切换炉次请求 H001 发出 请求 H002 发出 H002 先返回并显示 H001 后返回并覆盖 H002可以记录版本letloadVersion0;asyncfunctionloadHeatData(id:string){constversionloadVersion;const{data}awaitgetHeatDetail(id);if(version!loadVersion){return;}heatMeta.valuedata;}也可以使用AbortController或请求库提供的取消能力。十六、接口类型与数据校验const{data}awaitgetHeatDetail(heatId.value);heatMeta.valuedata;即使 API 函数声明了类型重要字段仍可能因后端异常缺失。可以检查if(!data||typeofdata.heat_id!string){thrownewError(模型服务字段缺失);}工业页面尤其需要区分请求失败接口成功但字段缺失字段存在但数据不可用数据可展示但不可用于模型。十七、加载函数的推荐结构asyncfunctionloadPageData(){if(!heatId.value){router.push(/heat);return;}loading.valuetrue;pageError.value;stopPlayback();stopPolling();try{const[detailResult,playbackResult,predictionResult]awaitPromise.allSettled([getHeatDetail(heatId.value),getHeatPlayback(heatId.value),getPrediction(heatId.value)]);handleDetailResult(detailResult);handlePlaybackResult(playbackResult);handlePredictionResult(predictionResult);if(displayMode.valuerealtime){awaitloadSnapshot();startPolling();}}finally{loading.valuefalse;awaitnextTick();resizeView();}}这类函数是页面数据加载的协调器。具体结果处理可以继续拆成小函数。十八、常见误区1. 所有接口都串行请求独立接口应考虑并行减少等待时间。2. 所有接口都放进Promise.all()可选模块失败时可能拖垮整个页面。3. Catch 中只打印控制台用户看不到错误页面也不知道是否应降级。4. 每个按钮都写一套请求逻辑首次加载和刷新应复用同一个函数。5. 实时轮询不处理请求重叠接口慢时会积累并发请求。6. 保留旧数据却不显示时间用户可能误把旧帧当成实时数据。十九、本章小结接口页面应建立四层能力API 封装 ↓ async/await 与加载状态 ↓ 并行请求与结果分流 ↓ 局部错误、旧帧保留和请求门控下一章将把前面知识组合起来实现实时轮询与历史数据回放。
返回列表