那天我在移动端 AI 识图里当电工
相册选图顺得像抹了黄油;一按 “直接拍照”,接口开始随机投喂 `Network Error`、`Abort`,像在抽盲盒。我一度想给 WebView 填工单:请咨询心理健康服务。
双端日志啃久了会上头。后来我把 “只有拍照才炸” 写进备忘录,配上时间线和请求草图,扔给 AI 当副驾驶。它不能替你抓包,但擅长把散装症状钉到几种常见剧本上:Page Visibility、SSE 默认策略、Upload 对 File 的二次包装——等于先画路线图,我负责踩油门验收。省的是瞎 grep 的命,不是思考的命。
这套业务人话版:图 multipart 上去,服务端排队跑视觉模型(吃像素张量,不吃 JSON 里华丽形容词),进度靠 SSE 往下淌。用户眼里是 “边识别边刷条”;所以 SSE 一断,不一定是模型罢工,也可能是管道先咽气——这句我跟产品复述过无数遍,比画时序图省事。
一、案发现场:拍照凭什么比相册狠?
相册路径: 系统相册弹起来,H5 多半还在前台晃,WebView 懒得睡。
拍照路径: 相机全屏占坑,内存紧的机器顺手把 WebView 塞进后台,`document.hidden` 变成 `true`,像被按了静音 nap。
对某些 SSE 实现来说,这一 nap 就是下班铃:hidden 就掐长连接,省流量省得理直气壮。你拍完照回到页面,管子里早凉了,你还在那儿假装上传——社死级别略高。
二、拆开看:连接层和数据层各来一刀
1. 连接层:SSE 跟 Page Visibility 的别扭婚姻
SSE 就是 HTTP 长连接 + 服务端单向吐事件,适合做进度、日志流这种配角戏。不少 polyfill(比如 `event-source-polyfill`)默认带着 “看不见就别折腾” 的家长式关怀——在相机场景里,关怀就是事故现场。
修法不玄学:打开 `openWhenHidden: true`,再用 `visibilitychange` 把重连和状态回补写成肌肉记忆。别幻想一条 SSE 扛全家,该短轮询、该退避重试就上;不然 PM 问 “为啥相册从不翻车”,你只能表演沉默是金。
2. 数据层:File 被组件库过度溺爱
Element Plus、Vant 一类为了预览、列表管理,会给 `File` 穿马甲:Proxy、包装对象应有尽有。你把整坨丢进 `FormData`,序列化一犯懒,服务端收到哲学意义上的 `[object Object]`——壳子在,肉没了,模型只能懵圈。
上传前扒一层:`file.raw` 或 `file.originFileObj`,确认 multipart 里是真 Blob。推理链路再花哨,入口永远是干净的二进制;这里偷一次懒,后面全是 “玄学调试” 陪跑。
三、几条在 Hybrid 里真能救命的土办法
出门前记账: 跳系统相机前,会话 id、任务 id 写下来,回来还能续命,别指望用户替你记。
长连接当电报: SSE/WebSocket 当 “尽量送达” 的通知网;关键结果要有接口或可追溯的存储兜底,断了还能圆回来。
上传流水线强迫症: 看见代理对象就问自己一句——这是原生 Blob 吗?不是?再剥一层皮。
四、收个尾
“相册正常、拍照必挂” 不像都市传说,拆开就是 宿主爱杀后台 + 前端爱包对象 的老双人舞。AI 帮我少在错误方向上通宵,但最后盖章的那几锤,还是手机里一遍遍复现敲出来的。
如果你也在容器里做识图、质检、扫描——愿你的长连接少断、你的 `FormData` 里永远有真肉。晚安请留给睡觉,别留给 silent disconnect。
本文属于 AI 实用主义流派 的第 2 篇肉身实战。
发表评论
分享你的想法和反馈