当前位置:首页 > 综合

前端如何获取后端数据

打开浏览器控制台,前端取后点开 Network 面板,何获刷新页面——你会看到一堆请求飞来飞去。端数这些请求就是前端取后前端获取后端数据的过程。没有它们,何获页面就是端数一张死图。

最原始的前端取后方式是 XMLHttpRequest。2000 年代初,何获微软在 Outlook Web Access 里搞出了这个东西,端数后来被各浏览器抄走。前端取后写法很啰嗦:

var xhr = new XMLHttpRequest(); xhr.open('GET',何获 '/api/user'); xhr.onreadystatechange = function() {  if (xhr.readyState === 4 && xhr.status === 200) {  console.log(JSON.parse(xhr.responseText)); } }; xhr.send();

能用,但没人愿意天天写这玩意儿。端数回调嵌套多了就是前端取后灾难。

2015 年 Fetch API 进了标准。何获它基于 Promise,端数写法干净不少:

fetch('/api/user') .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.error(err));

配合 async/await 更顺眼:

async function getUser() {  try {  const res = await fetch('/api/user'); if (!res.ok) throw new Error(res.status); return await res.json(); } catch (e) {  console.error(e); } }

Fetch 有个坑:HTTP 错误状态码(404、500)不会让 Promise 变成 rejected。你得手动检查 res.ok。我第一次踩这个坑时,接口返回 500,代码却继续往下跑,解析了一个错误页面,报了个莫名其妙的 JSON 解析错误。

实际项目里很少直接用裸 Fetch。axios 这类库更常见。它自动处理 JSON 转换、超时、请求取消、拦截器。拦截器特别实用——统一加 token、统一处理 401 跳登录,写一次全局生效。

请求发出去了,数据怎么回来?常见格式是 JSON。后端返回一个对象或数组,前端拿到后渲染到页面上。比如一个用户列表接口返回:

[ {  "id": 1, "name": "张三" }, {  "id": 2, "name": "李四" } ]

前端用 map 遍历,生成 DOM 或者交给框架处理。React、Vue 这些框架把数据绑定做得更彻底——数据变了,视图自动更新。你不需要手动操作 DOM。

跨域是绕不开的问题。浏览器出于安全考虑,默认禁止前端向不同源的后端发请求。解决方案有两种:后端设置 CORS 响应头,或者前端用代理。开发阶段用 webpack-dev-server 或 Vite 的 proxy 配置很常见:

// vite.config.js server: {  proxy: {  '/api': 'http://localhost:3000' } }

这样前端请求 /api/user 会被转发到后端,浏览器以为是同源,不拦。

还有一种情况:不想用 HTTP 请求,想实时拿数据。WebSocket 登场。它建立一个持久连接,后端可以主动推数据给前端。聊天室、股票行情、协同编辑这类场景用得多。Socket.IO 是对 WebSocket 的封装,处理了断线重连、降级兼容,用起来省心。

SSE(Server-Sent Events)是另一条路。它基于 HTTP,单向——只能后端推前端。比 WebSocket 简单,适合通知、日志流这类场景。我做过一个部署日志实时展示的功能,用的就是 SSE,后端每产生一行日志就推一条,前端 append 到页面上,效果不错。

数据拿到之后呢?缓存是个话题。同样的接口短时间重复请求很浪费。可以用内存缓存、localStorage、或者 Service Worker。React Query、SWR 这类库专门解决这个问题,它们帮你管理缓存、重试、轮询、乐观更新。用上之后代码量少很多。

最后提一句安全。前端拿数据,token 放哪里?localStorage 方便但 XSS 能偷走。httpOnly cookie 安全但 CSRF 要防。没有完美方案,看场景取舍。我倾向于 httpOnly cookie + CSRF token,麻烦一点但踏实。

前端获取后端数据,说到底就是发请求、收响应、处理数据。工具在变,从 XHR 到 Fetch 到各种封装库,核心逻辑没变过。选顺手的用就行。

分享到: