做稍大一点的 Angular 项目时,我最意外的发现是:很多前端 bug,根本不是前端的锅。组件逻辑没错,服务层正常,HTTP 请求返回 200,控制台干干净净——可界面就是不对劲。表格突然空了,表单死活提交不了,按钮凭空消失,因为某个条件语句悄悄变成了 false。大多数时候,Angular 本身没毛病,只是前端和后端说的已经不再是同一种语言了。
一切通常从一个很好消费的返回体开始。后端扔过来一套干净的结构,id、name、email,Angular 服务层用泛型接住,组件拿到数据,模板渲染出来,各自欢喜。然后后端开始演化:加个字段,给老字段改个名,把扁平属性塞进嵌套对象里。接口契约就这么变了,不动声色,刚好够在你眼皮底下埋一排细碎的雷。
破坏性变更并不总是敲锣打鼓地来。想象后端把 name 改成了 fullName——没有崩溃,没有报错,请求正常返回合法的 JSON。可前端每个写 user.name 的地方,此刻拿到的全是 undefined。有时候 Angular 直接渲染空字符串,有时候管道突然不可理喻,有时候条件判断静默地算成了 false。这类 bug 不费脑子,但费命,不是因为难修,而是因为太难察觉。
我很长一段时间都有一个错觉,以为 TypeScript 的 interface 能保证后端返回的数据形状。interface 里明明写了 id、name、email,然后挂上泛型发起请求,看着挺安全。但那个泛型只是告诉 TypeScript“我期望收到什么”,它完全不会验证网络上真正过来了什么。如果后端忽然返回了一个 fullName 而不是 name,TypeScript 一声不吭,Angular 照样编译通过,问题只在运行时才炸开。这个认知直接推翻了我对 API 集成的理解:interface 是给开发者看的文档,不是运行时的校验。
更蠢的是我一开始的修法:让每个组件各自适配后端的变动。一个页面里好几处都在展示用户信息,后端一改,我本能地挨个组件去修,这里做后备取值,那里补容错兜底。很快,不同组件里散落着重复的适配逻辑,维护起来痛苦得一塌糊涂。后来才反应过来,处理这类变化的最佳位置根本不在组件里,应该在最靠近 HTTP 边界的地方做一层数据转换,把后端返回的 raw 数据映射成前端真正需要的形状。这样,无论后端怎么改,前端内部世界始终保持一致的约定,变动的脏活只集中在一处。Angular 没报错的时候,往往才是你最需要警惕的时候——沉默的契约撕裂,比抛异常更消耗团队的调试时间。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.